4

In a callback method I am attempting to get the text property of a textBox like this:

string postData = tbSendBox.Text;

But because its not executed on the UI thread it gives me a cross-thread exception.

I want something like this:

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

But this runs asynchronously. The synchronous version is:

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

But Dispatcher.Invoke() does not exist for the Windows Phone. Is there something equivalent? Is there a different approach?

Here is the whole function:

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);
    }
Lemontongs
  • 185
  • 3
  • 7

3 Answers3

9

No you are right you can access only to the async one. Why do you want sync since you are on a different thread of the UI one?

Deployment.Current.Dispatcher.BeginInvoke(() =>
       {
            string postData = tbSendBox.Text;
        });
MatthieuGD
  • 4,552
  • 2
  • 30
  • 29
  • Because I need to set the postData variable to the Text of the textBox before continuing through the rest of the function. I guess my overall question is: How do I **GET** UI properties from a thread that is not the UI thread. – Lemontongs Nov 04 '11 at 02:49
  • OR, how do I call a callback function with arguments, IE: `myReq.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback **ARGUMENTS??**), myReq);` – Lemontongs Nov 04 '11 at 02:54
  • 1
    I think it defeats the purpose of the async model of Windows Phone: UI has priority over all other backgrounsd tasks to prevent bad experience for the user (slow rendering etc..). Maybe you mitigate by displaying a mesage like "loading" or "updating" .... – MatthieuGD Nov 04 '11 at 13:24
2

This should make an asynchronous call to a synchronous :

  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;
Ivan Bianko
  • 1,749
  • 15
  • 22
  • I tried this. It seems to make sense but the thread gets blocked on WaitOne() before dispatching to the other thread so it never gets to the Set() – Lemontongs Nov 05 '11 at 19:15
  • @Lemontongs, you are wrong. if you execute this code in non-ui thread it works as you need.. ps. I use this code in my programs to make sync operations. – Ivan Bianko Nov 06 '11 at 00:45
0

1) Obtain a reference to the synchronization context of UI thread. For example,

SynchronizationContext context = SynchronizationContext.Current

2) Then post your callback to this context. This is how Dispatcher internally works

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

Is it what you want?

Tony Kh
  • 1,512
  • 11
  • 8