Рейтинг:
0
Richard Deeming
Вы используете BackgroundWorker
чтобы подтолкнуть работу к фоновому потоку. Но вы тут же звоните Dispatcher.Invoke
чтобы вернуть работу обратно в поток пользовательского интерфейса.
В результате вы блокируете поток пользовательского интерфейса до тех пор, пока ваша работа не завершится, и оставляете фоновый поток бездействующим, ожидая, пока ваш поток пользовательского интерфейса закончит свою работу.
Вам нужно переместить как можно больше работы в фоновый поток. Снимите наружный Dispatcher.Invoke
позвоните в свой worker_DoWork
метод. Когда вам нужно обновить пользовательский интерфейс, используйте ReportProgress
метод передачи данных обратно в поток пользовательского интерфейса.
Предполагая, что он обновляет DetailReportFCBuySell
свойство, которое должно произойти в потоке пользовательского интерфейса, должно работать примерно так:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
var batchFCSB = new System.Data.DataTable();
int row = 0;
if (DetailReportFCBuySell.FirstOrDefault().TotalRecords > toFetchRecords)
{
long RecordsIcrease = 1000;
batchFCSB = DetailReportFCBuySell.ToDataTable();
row = 1;
PageIndex++;
for (long k = toFetchRecords; k < DetailReportFCBuySell.FirstOrDefault().TotalRecords; k = +toFetchRecords)
{
new AlxServiceClient().Using(channel =>
{
var temp = AlyexWCFService.DL.DLTTIn.FCBuySELL(transactionName, isDetails, Convert.ToDateTime(dateEdtStartDate.EditValue).Date, Convert.ToDateTime(dtpEditEndDate.EditValue).Date, Customerid, ProductID, branchID, NoOfRecords, PageIndex - 1, isBuy);
worker.ReportProgress(0, temp);
row++;
PageIndex++;
});
toFetchRecords = toFetchRecords + RecordsIcrease;
}
}
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var temp = (ObservableCollection<dlreports.fcbuyselldetail>)e.UserState;
DetailReportFCBuySell = DetailReportFCBuySell.Union(temp).ToObservableCollection();
}
NB: Вам нужно будет установить
worker.WorkerReportsProgress
собственность на
true
, и провод вверх по
worker_ProgressChanged
метод к
worker.ProgressChanged
событие.
SwethaVijayan
Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку.
эта ошибка обнаружена с помощью avoid the dispacher
Richard Deeming
Так что, как я уже сказал, двигайтесь просто код, который получает доступ / обновляет пользовательский интерфейс к потоку пользовательского интерфейса.
Если вы используете диспетчер для перемещения всего worker_DoWork
функция возвращается в поток пользовательского интерфейса, тогда вы можете с таким же успехом не утруждать себя использованием BackgroundWorker
во-первых.
SwethaVijayan
чтобы избежать этого, что я должен сделать. мне нужно избегать применения waing в течение длительного времени. пожалуйста, дайте мне подходящий ответ .
Richard Deeming
Как я вам уже говорил, переместите как можно больше кода в фоновый поток. Только код, который обращается к пользовательскому интерфейсу или обновляет его, должен быть возвращен обратно в поток пользовательского интерфейса.
Я уже дал вам "подходящий ответ"; вам просто нужно прочитать и понять его.
SwethaVijayan
я должен был удалить диспетчера, как вы сказали в моей программе, и я сделал это другим способом.
частная btnExrtPDF_Click недействительным(объект отправителя, RoutedEventArgs е)
{
if (DetailsOrSummary = = " подробности")
isDetails = истина;
//FetchRecord();
// Task myFirstTask = задача.Factory.StartNew(FetchRecord);
lblStatus.Text = ("Прогресс:" + 0 + "%");
thread = new Thread(new ThreadStart(FetchRecord));
нить.Начать();
}
частный недействительными FetchRecord()
{
пробовать
{
если (приложение.Текущий.Диспетчер.Метод checkaccess())
{
if (DetailsOrSummary = = " подробности")
isDetails = истина;
DetailReportFCBuySell = AlyexWCFService.DL.DLTTIn.FCBuySELL(transactionName, isDetails, Convert.Объект todatetime(dateEdtStartDate.EditValue).Дата, Конвертация.Объект todatetime(dtpEditEndDate.EditValue).Дата, Customerid, ProductID, branchID, NoOfRecords, PageIndex-1, isBuy);
long RecordsIcrease = 1000;
Pageindex было++;
for (long k = toFetchRecords; k & lt; DetailReportFCBuySell.Метода firstordefault().TotalRecords; k = +toFetchRecords)
{
новый AlxServiceClient (). Using(channel = & gt;
{
ObservableCollection< DLReports.FCBuySellDetail> temp = AlyexWCFService.DL.DLTTIn.FCBuySELL(transactionName, isDetails, Convert.Объект todatetime(dateEdtStartDate.EditValue).Дата, Конвертация.Объект todatetime(dtpEditEndDate.EditValue).Дата, Customerid, ProductID, branchID, NoOfRecords, PageIndex-1, isBuy);
DetailReportFCBuySell = DetailReportFCBuySell.Союз (temp).ToObservableCollection();
Pageindex было++;
});
toFetchRecords = toFetchRecords + RecordsIcrease;
}
ResultsData = DetailReportFCBuySell.ToDataTable ();// (Коллекция.Где (i => i. Key == k).FirstOrDefault (). Value);
ExportToOxml(правда);
}
ещё
{
// Другой мудрый повторный вызов метода с доступом к потоку пользовательского интерфейса
Приложение.Текущий.Диспетчер.Invoke (новая система.Действие (() = & gt; FetchRecord()));
}
}
поймать (исключение бывший)
{
бросок экс;
}
}
таким образом, я также получаю ту же ошибку, что и приложение, ожидающее 30 секунд
Richard Deeming
Нет! Вы все еще передача всей работы обратно в поток пользовательского интерфейса.
Вы запускаете новый фоновый поток для выполнения FetchRecord
метод. Затем этот метод вызывает CheckAccess
, который возвращается false
поскольку вы находитесь в фоновом потоке. Затем метод вызывает Invoke
чтобы вызвать метод в потоке пользовательского интерфейса.
Опять же, вы блокируете поток пользовательского интерфейса до тех пор, пока ваш метод не завершится, и оставляете фоновый поток бездействующим, ожидая, пока поток пользовательского интерфейса завершит выполнение вашего метода.
Вам нужна трудоемкая работа для запуска в фоновом потоке. Он должен перезванивать в поток пользовательского интерфейса только тогда, когда ему нужно получить доступ к пользовательскому интерфейсу или обновить его.
Если вы собираетесь продолжать толкать все обратно в поток пользовательского интерфейса, то вы можете вообще не использовать фоновый поток.
То, что вы делаете, по сути, то же самое, что нанять помощника, который поможет вам сделать больше работы. Но каждый раз, когда вы даете работу своему помощнику, он просит вас сделать это за него, сидит и ждет, пока вы закончите. Когда вы закончите выполнять его работу, вы передаете ему результаты, а он затем возвращает их вам и говорит: "работа сделана" Вы не успеваете сделать больше никакой работы, а ваш помощник (фоновый поток) совершенно бесполезно.
SwethaVijayan
хорошо, я понял проблему, но как я могу это сделать ,пожалуйста, помогите мне.
Richard Deeming
Еще раз: выполняйте работу в фоновом потоке и только вызывайте Invoke
когда вам нужно получить доступ или обновить пользовательский интерфейс.
Начните с того, что не звоните никому. Invoke
. Когда вы получите "вызывающий поток" исключение, посмотрите на стек вызовов, чтобы увидеть, к чему вы пытаетесь получить доступ. Подвиньте этот конкретный бит вашего кода в Invoke
позвони и попробуй еще раз. Повторяйте до тех пор, пока код не будет работать без исключения.
И помните, что использование фонового потока не ускорит ваш код; он просто сохранит пользовательский интерфейс отзывчивым, пока ваш код работает.
SwethaVijayan
можете ли вы привести один пример со мной?
Richard Deeming
Если вы используете BackgroundWorker
, и вам нужно только обновить пользовательский интерфейс, а затем ReportProgress
будет делать свою работу - как я написал в своем ответе.
Для всего остального используйте Dispatcher.Invoke
во исполнение конкретный фрагмент кода в потоке пользовательского интерфейса.