在Windows Phone 7上进行Dispatcher.Invoke()操作?

4
在回调方法中,我正在尝试获取文本框的文本属性,代码如下:
string postData = tbSendBox.Text;

但是因为它不在UI线程上执行,它会给我一个跨线程异常。

我想要这样的东西:

Dispatcher.BeginInvoke(() =>
{
    string postData = tbSendBox.Text;
});

但这是异步运行的。同步版本如下:
Dispatcher.Invoke(() =>
{
    string postData = tbSendBox.Text;
});

然而,在Windows Phone中不存在Dispatcher.Invoke()。是否有等效的替代方法?或者有其他方法来解决这个问题吗?

以下是完整的函数:

public void GetRequestStreamCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

        // End the operation
        Stream postStream = request.EndGetRequestStream(asynchronousResult);

        string postData = tbSendBox.Text;

        // Convert the string into a byte array.
        byte[] byteArray = Encoding.UTF8.GetBytes(postData);

        // Write to the request stream.
        postStream.Write(byteArray, 0, postData.Length);
        postStream.Close();

        // Start the asynchronous operation to get the response
        request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
    }
3个回答

9

你说得没错,你只能访问异步的线程。既然你在UI线程之外,为什么还需要同步呢?

Deployment.Current.Dispatcher.BeginInvoke(() =>
       {
            string postData = tbSendBox.Text;
        });

因为我需要在继续函数的其余部分之前将postData变量设置为textBox的文本。我的总体问题是:如何从非UI线程获取UI属性。 - Lemontongs
或者,我如何调用带参数的回调函数,例如:myReq.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback **参数??**), myReq); - Lemontongs
1
我认为这违背了Windows Phone异步模型的初衷:UI优先于所有其他后台任务,以防止用户体验不佳(如渲染缓慢等)。也许您可以通过显示诸如“加载”或“更新”之类的消息来缓解这种情况... - MatthieuGD

2
这应该是对同步调用进行异步调用的过程:
  Exception exception = null;
  var waitEvent = new System.Threading.ManualResetEvent(false);
  string postData = "";
  Deployment.Current.Dispatcher.BeginInvoke(() =>
  {
    try
    {
      postData = tbSendBox.Text;
    }
    catch (Exception ex)
    {
      exception = ex;
    }
    waitEvent.Set();
  });
  waitEvent.WaitOne();
  if (exception != null)
    throw exception;

我尝试过这个方法。它似乎是有道理的,但线程在调度到另一个线程之前会被WaitOne()阻塞,因此永远无法到达Set()。 - Lemontongs
@Lemontongs,你错了。如果你在非UI线程中执行这段代码,它会按照你的需求工作。顺便说一句,我在我的程序中使用这段代码来进行同步操作。 - Ivan Bianko

0

1) 获取UI线程的同步上下文的引用。例如,

SynchronizationContext context = SynchronizationContext.Current

2) 然后将您的回调发布到此上下文中。这是 Dispatcher 内部工作的方式。

context.Post((userSuppliedState) => { }, null);

这是你想要的吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接