2013-12-16 155 views
0

我遇到了WinRT项目的问题。目前程序上的执行是在两个线程上运行的。一个线程执行主应用程序,另一个线程处理事物的UI方面。目前,我有一个问题,从主线程调用一个函数在UI线程上执行,等待一个回复,然后在主线程上继续执行......让我向您展示一些代码作为示例。WinRT跨线程同步异步调用

public async void SignOut(Action onSuccess, Action onFailure) 
{ 
    bool success = false; 
    bool wait = true; 

    CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => 
    { 
     await SignOutAsync(); 
     success = true; 
     wait = false; 
    }); 

    while (wait) { } 

    if (success) 
    { 
     onSuccess(); 
    } 
    else 
    { 
     onFailure(); 
    } 
} 

所以这段代码是做什么的我想要它做的,但它显然不是去了解它与忙等待和所有的正道。问题是,如果我将OnSuccess/OnFailure执行移入RunAsync lambda,那么关于无效内存的回调会出现错误,因为执行在不同的线程上。目前我面临的问题是,我无法在不影响执行顺序的情况下排除繁忙的等待。理想情况下,我想等待整个RunAsync lambda在UI线程上完成执行,然后返回到主线程以运行成功/失败回调。

当我点击RunAsync lambda的await SignOutAsync()部分时,RunAsync任务将其自身标记为完整,并在SignOutAsync方法有任何结果之前返回成功/失败检查。我相信这是由于嵌套的异步方法,你不能真正等待RunAsync调用,然后再次在其中的异步lambda。

任何意见将不胜感激。

回答

0

当前程序上的执行运行在两个线程上。一个线程执行主应用程序,另一个线程处理事物的UI方面。

这并不理想。如果可能的话,结构化你的代码,以便你只有一个“特殊”线程(UI线程)。 async允许您的UI线程保持响应而不需要第二个“特殊”线程。

目前,我有一个问题,从主线程调用一个函数在UI线程上执行,等待答复,然后继续执行主线程。

再一次,更好的设计是让程序逻辑为UI提供“服务”,而不是其他方式。因此,尽你所能重新设计调用,以便UI驱动程序逻辑,而不是相反。

也就是说,如果你绝对是必须有有一个“特殊”后台线程,你可以使用AsyncContextThread type from my AsyncEx libraryAsyncContextThread了解异步方法,所以你可以这样做:

public async Task SignOutAsync(Action onSuccess, Action onFailure) 
{ 
    try 
    { 
     await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => SignOutAsync()); 
     onSuccess(); 
    } 
    catch 
    { 
     onFailure(); 
    } 
} 

不过,我会不好意思把这个代码投入生产;任何使用Dispatcher的东西都是代码味道。尽管我编写了AsyncContextThread类型,但我无法将其推荐用于Windows应用商店项目。一个更好的设计是构造代码,以便程序逻辑永远不会回调到UI中。