WebClient - 与大数据同步响应

时间:2012-04-02 09:44:09

标签: .net windows-phone-7 asynchronous webclient

我正在使用WebClient从服务器获取一些JSON数据。我希望它是同步的(是的,我知道在WP中一切都应该是异步的,但我需要从某种原因进行同步)。在我的班上,我有这样的代码:

    private WebClient _webClient;
    private string _acctualResponse;
    private AutoResetEvent _lock = new AutoResetEvent(false);

    void _webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
    {
        _acctualResponse = e.Result;
        _lock.Set();
    }

    public string _message;
    public string SendString(string URL, string message)
    {
        _webClient.UploadStringAsync(new Uri(URL), message);
        _lock.WaitOne();
        return _acctualResponse;    
    }

在我的程序中,我正在使用它来获取一些不同的数据集。一切正常,返回数据很少。当我必须获得更大的数据(base64中的3 img)时,事件无法启动。 但! 当我删除_lock时,事件总是在SendString函数结束后开始。我尝试使用其他一些机制等待响应,例如while循环:

    private void WaitForResponse()
    {
        _acctualRequestTime = 0;
        _acctualResponse = null;
        while (!_uploadComplet && _acctualRequestTime < Timeout)
        {
            int slepTime = 200;
            Thread.Sleep(slepTime);
            _acctualRequestTime += slepTime;
        }
        _uploadComplet = false;
    }

[当然,事件我将_uploadComplete标志设置为true] 效果是相同的:无论设置了什么超时间隔,响应在超时后都会短暂。 我对这种情况感到有点困惑。你知道我做得不好吗?

2 个答案:

答案 0 :(得分:1)

我也有这个问题。

您可以使用:

public T Get<T>(string apiMethod) where T : class
        {
            T outputObject;
            lock (syncObj)
            {
                downloadHandle = new ManualResetEvent(false);

                ThreadPool.QueueUserWorkItem(new WaitCallback(DownloadAsync), apiMethod);
                downloadHandle.WaitOne();
                outputObject = JsonHelper.Parse<T>(result);
            }
            return outputObject;
        }

protected void DownloadAsync(object _uri)
        {
            try
            {
                var url = _uri as string;
                WebClient client = new WebClient();
                client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
                client.DownloadStringAsync(new Uri(GLOBALS.MAIN_API_URL + url, UriKind.Absolute));
            }
            catch (Exception ex)
            {
                downloadHandle.Set();
            }
        }

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            (sender as WebClient).DownloadStringCompleted -= client_DownloadStringCompleted;

            try
            {
                result = e.Result;
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            finally
            {
                downloadHandle.Set();
            }
        }

现在你可以这样使用:

public Song GetSong(int _id)
        {
            var wr = Get<SongInfoWrapper>("info/song/" + _id);
            if (wr != null)
            {
                if (wr.Error == null)
                {
                    return wr.Element;
                }
            }

            return null;
        }

但可以肯定的是,GetSong方法在UI线程中没有调用。

答案 1 :(得分:0)

如果在UI线程上启动了请求,则

WebClient会在UI线程上引发事件。因此,如果您正在等待UI线程并且不控制主事件循环,则事件将排队,因此永远不会传递。

由于WebClient执行UI线程上的所有处理,Microsoft和许多其他人建议不要使用它。相反,应该使用WebRequest。它甚至可以解决你的问题。 (虽然阻止UI线程并不是一件好事。)