2010-05-16 36 views
0

我读过我可以使用异步调用与轮询,特别是当调用者线程为GUI提供服务时。我看不到如何,因为:异步轮询可用于GUI线程

while(AsyncResult_.IsCompleted==false) //this stops the GUI thread 
{ 
} 

那么它是如何来它应该是好的这个目的?我需要更新我的GUI状态栏每次deamon线程做了一些进步..

+0

你检查的BackgroundWorker类?看起来像一个很好的解决方案(http://msdn.microsoft.com/en-us/library/hybbz6ke.aspx) – CharlesB 2010-05-16 11:50:46

回答

1

你是正确的在你的while循环停止GUI线程,当这样做时,你不想这样做。

如果您需要轮询,最好是设置一个计时器,并检查计时器触发时工作是否完成。定时器可以有一个小的分辨率没有问题(例如100毫秒),只要你在每次打勾时不做太多的工作。

但是,我认为你会比using a callback更好,所以你不需要轮询并在你的工作量完成后立即得到通知。

+0

随着回调,我不能让主线程知道(至少我读了什么) - 它只是当调用者线程不需要知道reslts。 – Thomas 2010-05-16 11:35:58

+0

@Tomas,回调将在另一个线程上执行,这是正确的,但是在更新GUI(使用Control.Invoke)或使得生成的数据可供GUI线程使用时没有问题。 – driis 2010-05-16 12:41:50

0

异步轮询的要点是,您可以在检查IsCompleted - 例如服务GUI事件之间执行其他操作。例如,您可以设置一个计时器,以每秒触发一次事件来检查异步操作是否完成,并使用正常的GUI事件循环将这些事件与GUI接收的所有其他事件一起处理。这样,您的GUI仍然是响应式的,并且在异步操作完成后不久,您的计时器事件处理程序将会注意到它。

+0

谢谢,我想到了计时器,但由于我没有经历,我认为这是一个坏主意:) – Thomas 2010-05-16 11:30:23

0

我与旧版API暴露BeginExecute()EndExecute()时遇到同样的问题。 BeginExecute()开始异步操作,然后沉默,直到它完成执行到最后。但是我需要实时更新执行进度的中间状态。 于是我想出了以下解决方案:

var asyncResult = command.BeginExecute(); 
while (!asyncResult.IsCompleted) 
{ 
    if (command.State != OldState) 
    { 
     progress.Report(newState); 
    } 

    // Key piece in this polling loop. 
    await Dispatcher.Yield(DispatcherPriority.ApplicationIdle); 
} 
command.EndExecute(asyncResult); 

起初我用

await Task.Yield(); 

但后来我发现,在WPF它不会返回控制到GUI,因为这个循环将具有更高的优先权。这就是为什么我切换到该指令:

await Dispatcher.Yield(DispatcherPriority.ApplicationIdle); 

所以现在GUI将检查和更新的进展,只有当它没有其他事情做:)