为什么ManualResetEvent无法在使用Silverlight 4的同步调用中工作?

时间:2011-05-27 02:38:36

标签: multithreading silverlight-4.0 concurrency asynchronous

让我们暂时搁置一下,question是否应该在Silverlight应用程序的上下文中尝试类似同步操作。如果我使用ManualResetEvent,如下面的代码所示:

    static string result;
    static AutoResetEvent are = new AutoResetEvent(false);
    static ManualResetEvent mre = new ManualResetEvent(false);
    public static string AsyncCall()
    {
        string url = "https://stackoverflow.com/feeds/tag/silverlight";
        WebClient w = new WebClient();
        w.DownloadStringCompleted += new DownloadStringCompletedEventHandler(w_DownloadStringCompleted);
        w.DownloadStringAsync(new Uri(url), url);
        mre.WaitOne();
        return result;
    }

    static void w_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        result = e.Result;
        mre.Set();
    }

正如您期望阅读ManualResetEvent on MSDN,“当控制线程完成活动时,它调用Set方法来表示等待线程可以继续。”,当在w_DownloadStringCompleted中调用Set()时, control返回到在AsyncCall中开始等待的等待线程。这是使用.NET 4.0运行时发生的情况。 AsyncCall中的线程被阻止,直到下载完成并调用Set。

如果我在Silverlight 4中运行相同的代码,将调用DownloadStringAsync,但控件永远不会到达w_DownloadStringCompleted回调。一旦调用了WaitOne(),AsyncCall中的那个线程就会挂起,并且处理DownloadStringAsync的线程永远不会到达回调。我看到线程到达SL4中的下载回调的唯一方法是来自AsyncCall的线程是否从AsyncCall返回。所以Set()永远不会被调用。

为什么ManualResetEvent在Silverlight 4中没有按预期工作?为什么它与.NET 4不同? 这可能是微软对异步设计模式的执行吗? 或者有什么我想念的东西?

由于

1 个答案:

答案 0 :(得分:3)

Silverlight中的网络回调将始终以与发起时相同的线程到达。例如,如果在UI线程上创建WebClient.DownloadStringAsync(即,在按钮单击事件上),则回调调用将排队以在同一UI线程上传递。但是,您对mre.WaitOne()的调用阻止了UI线程,因此永远不会调用回调,并且mre.Set()调用永远不会发生。

所以是的,这是网络调用的异步性中的一种强制执行 - 你真的不能进行同步调用,即使它们似乎是同步的。