2015-09-28 2 views
2

Может ли результат async operation быть возвращен в инициированную им нить (то есть AsyncCallback, вызванной в исходной теме)?Возврат результата операции async к исходной теме

Вот пример

void Main(string[] args) 
    { 

     Func<bool> action =() => 
     { 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Running"); 
      return true; 
     }; 

     AsyncCallback onComplete = (r) => 
     { 
      bool result = action.EndInvoke(r); 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Completed"); 
     }; 

     Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Main"); 
     IAsyncResult iar = action.BeginInvoke(onComplete, null); 
    } 

Его выход что-то вроде:

5: Main 
6: Running 
6: Completed 

То, что я хотел бы достичь является onComplete обратного вызова выполняется в главном потоке (например Заполненная и Main будет. имеют тот же самый идентификатор резьбы, напечатанный в этом примере)

(Я знаю, это может быть достигнуто с помощью BackgroundWorker, т. е. этоВ исходной цепочке запускается событие 10, поэтому возвращаемое значение функции, вызванной в фоновом потоке, может быть возвращено в исходную нить)

+0

Так почему бы не просто использовать BackgroundWorker? Он не запечатан, поэтому вы можете даже извлечь из него свою магию. – Nebula

+0

Изначально вы можете отправить ссылку на основной поток вместе с вашей задачей, а перекрестный поток - на него. Но проверить это и убедиться, что он всегда работает? Brrr ... – Nebula

+2

@ Небула доступ к 'Thread' не позволяет вам нажимать * работать * на поток; для этого вам нужен какой-то механизм очереди работы. –

ответ

5

В основном речь идет о реализациях и TaskScheduler, которые вы решите использовать. В случае многих интерфейсов пользовательского интерфейса (winforms, WPF и т. Д.), То да: если вы начнете работу с потоком пользовательского интерфейса, обратный вызов может произойти в потоке пользовательского интерфейса, но это не применяется в общем случае, где поток ThreadPool с большей вероятностью победит. В конечном счете, вы не можете просто принудительно вернуть работу к определенному потоку, , если, что нить по дизайну проверяет некоторые очереди работы и выполняет декомпрессию/выполнение пакетов работы по мере их поступления (что точно соответствует структуре пользовательского интерфейса) ,

+0

Итак: просто используйте любой тип нити, соответствующий вашему счету? Или это слишком грубо? – Nebula

+0

Предполагая, что это приложение WPF, я могу сделать что-то вроде 'action.BeginInvoke ((r) => Dispatcher.BeginInvoke (onComplete (r)), null)' ie. когда действие завершается на вторичном потоке, оно будет стоять в очереди на обратный вызов 'onComplete' в потоке пользовательского интерфейса? Но было интересно, есть ли другой способ сделать это (без явного вызова Dispatcher) - что-то вроде установки 'SynchronizingObject', чтобы не было нулевого в' Timer'. – ubi

+0

@ubi, если вы начинаете с потока пользовательского интерфейса, он должен работать нормально –

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