У меня есть проект WinForms (уже несколько лет), который в настоящее время находится в .NET 4.0. Большая часть текущего поиска данных использует класс BackgroundWorker
для асинхронного поиска, но я в середине добавляю некоторые новые функции и хотел использовать шаблон async
(через Async Targeting Pack). Этот подход отлично работает в среде разработки и тестирования, но некоторые (нетривиальное число) наших пользователей получают ошибки в программе, которые, как представляется, связаны с потоковой обработкой; в частности, что вы можете увидеть, если у вас есть что-то другое, кроме потока пользовательского интерфейса, изменяющего данные, привязанные к UI.Может ли использование async/wait с TPL вмешиваться в BackgroundWorker?
Пример одного из элементов управления унаследованного бы:
public class LegacyControl
{
public void LoadData(int id)
{
while(isLoading)
{
Application.DoEvents();
Thread.Sleep(50);
}
isLoading = true;
currentId = id;
worker.RunWorkerAsync(id);
}
private bool isLoading;
private int currentId;
private object myData;
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
myData = RetrieveData(currentId);
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bindingSource.DataSource = myData;
}
}
Пример одного из новых элементов управления будет:
public class NewControl
{
public void LoadData(int id)
{
LoadDataAsync(id).ContinueWithErrorHandling(); // custom extension method to generically handle unhandled task exceptions.
}
private async Task LoadDataAsync(int id)
{
var data = await RetrieveSomeOtherDataAsync(id);
bindingSource.DataSource = data;
}
}
Хотя я сомнителен об этой возможности, я «Я вытаскиваю свои волосы, пытаясь понять, что здесь происходит. Есть ли вероятность, что использование async
/await
каким-то образом испортит BackgroundWorker
и, скажем, вызывает его RunWorkerCompleted
событие для запуска на фоне нити вместо потока пользовательского интерфейса?
Я могу попытаться удалить код TPL, но поскольку я не могу воспроизвести ошибочное поведение в моей среде, у меня нет никакого способа тестирования.
Я согласен, но тот факт, что эта проблема возникла именно тогда, когда было введено первое использование 'async' /' await', трудно игнорировать. Хотя я согласен с тем, что «DoEvents» следует избегать, и я не использую его сам, эти компоненты существуют уже несколько лет. –
Ошибки reentrancy чрезвычайно распространены, и 'DoEvents' будет обрабатывать эти ошибки в зависимости от сотен других вещей, таких как загрузка машины, сторонние приложения, мощность процессора и почти все, что влияет на точное время кода. Таким образом, это может быть вызвано некоторыми неясными моментами, которые немного отличаются при добавлении компонентов «async», но мои деньги находятся в основной проблеме, находящейся в «DoEvents». –