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

T. *_*ter 5 concurrency multithreading asynchronous silverlight-4.0

让我们暂时搁置一下,是否应该在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();
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

谢谢

car*_*ira 3

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

所以,是的,这是网络调用异步性的一种强制 - 你确实不能进行同步调用,即使它们看起来是同步的。