0

У меня есть проект 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, но поскольку я не могу воспроизвести ошибочное поведение в моей среде, у меня нет никакого способа тестирования.

ответ

3

async не будет связываться с BackgroundWorker. BackgroundWorker - это собственная полностью независимая нить.

Самая подозрительная часть кода, который вы отправили, - DoEvents. Это создает вложенный цикл сообщений, поэтому вам нужно подумать о своем полном приложении и убедиться в том, что любой обработчик события UIasync), который вы будете иметь, будет работать правильно, если вызвано этим методом.

+0

Я согласен, но тот факт, что эта проблема возникла именно тогда, когда было введено первое использование 'async' /' await', трудно игнорировать. Хотя я согласен с тем, что «DoEvents» следует избегать, и я не использую его сам, эти компоненты существуют уже несколько лет. –

+1

Ошибки reentrancy чрезвычайно распространены, и 'DoEvents' будет обрабатывать эти ошибки в зависимости от сотен других вещей, таких как загрузка машины, сторонние приложения, мощность процессора и почти все, что влияет на точное время кода. Таким образом, это может быть вызвано некоторыми неясными моментами, которые немного отличаются при добавлении компонентов «async», но мои деньги находятся в основной проблеме, находящейся в «DoEvents». –

Смежные вопросы