在Windows Phone Silverlight应用程序8/8.1中同步等待Web服务时,主线程冻结

本文关键字:Web 服务 冻结 线程 等待 Silverlight Phone Windows 应用程序 同步 | 更新日期: 2023-09-27 18:29:44

我有一个Windows Phone Silverlight应用程序。我知道我所问的不是一个好的编程实践,但我仍然不明白为什么这个案例在Silverlight中不起作用。

我试图做的是从主线程同步调用Web服务,等待另一个线程来完成工作。

        HttpClient httpClient = new System.Net.Http.HttpClient();
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "Web service address");
        AutoResetEvent showSplash = new AutoResetEvent(false);
        Thread uiThread = new Thread(async () =>
        {
            await httpClient.SendAsync(request);
            showSplash.Set();
        });
        uiThread.IsBackground = true;
        uiThread.Start();
        showSplash.WaitOne();

我也试过这个代码,但它仍然冻结:

        HttpClient httpClient = new System.Net.Http.HttpClient();
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "Web service address");
        Task<HttpResponseMessage> response = Task.Run(async () => await httpClient.SendAsync(request));
        response.Wait();

由于某些原因,主线程冻结,代码的执行在Wait()方法处停止。有趣的是,这行代码在简单的WPF应用程序、Windows Phone 8.1 RT等中运行良好。

在Windows Phone Silverlight应用程序8/8.1中同步等待Web服务时,主线程冻结

阻止UI线程通常是个坏主意,但在这种情况下,这实际上是一个绝对不能做的事情。

在Windows Phone中发出HTTP请求的所有方法在某个时候都需要UI线程(原因我不知道)。也就是说,执行请求的方法的某些部分在UI线程中执行。所以,阻止它会阻止请求的发出,所以你不会得到结果,线程也永远不会被阻止。

我建议你找到一种方法,在不阻塞UI线程的情况下完成你正在做的事情。我只见过一种情况,你真的需要阻止它…在这种情况下,我使用套接字发出请求,但这只是在你找不到任何其他解决方案的情况下。

httpClient.SendAsync()将在单独的线程上调用。没有什么你真正需要做的。

public async void Button1Click(object sender, EventArgs e)
{
    HttpClient httpClient = new System.Net.Http.HttpClient();
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "Web service address");
    button1.Enabled = false;
    await httpClient.SendAsync(request);
    // this line will be called back on the main thread.
    button1.Enabled = true;
}

它可能是阻塞的,因为您正在使用Wait()和WaitOne()。这些调用正在阻塞当前线程。您应该使用wait。不过您同时使用了wait和wait()

http://msdn.microsoft.com/en-us/library/hh191443.aspx

你可能想要这样的东西。它不会启动新线程,但会异步运行,这样UI线程就不会被阻塞。

  HttpClient httpClient = new System.Net.Http.HttpClient();
  HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "Web service address");
  Task<HttpResponseMessage> response = await httpClient.SendAsync(request));