开发者

UI Thread/Dispatcher Issue (BeginInvoke)

In a previous question I asked how to get access to UI elements in a callback thread. I got a lot of good answers, one of which was to implement a wrapper class such as this:

public static class UIThread
{
    private static readonly Dispatcher Dispatcher;

    static UIThread()
    {
        Dispatcher = Deployment.Current.Dispatcher;
    }

    public static void Invoke(Action action)
    {
        if (Dispatcher.CheckAccess())
        {
            action.Invoke();
        }
        else
        {
            Dispatcher.BeginInvoke(action);
        }
    }
}

And you can call this using

UIThread.Invoke(() => TwitterPost.Text = "hello there");

However I tried extending this by calling the following in my callback function

UIThread.Invoke(() => loadUserController(jsonObject));

with the following method:

private void loadUserController(JObject jsonObject)
{
    string profile_image_url = (string)jsonObject["profile_image_url"];
    string screen_name = (string)jsonObject["screen_name"];
    string name = (string)jsonObject["name"];
    string location开发者_JS百科 = (string)jsonObject["location"];
    int statuses_count = (int)jsonObject["statuses_count"];

    if (!string.IsNullOrEmpty(profile_image_url))
    {
        ProfileImage.Source = new BitmapImage(new Uri("blahblahbalhb.jpg", UriKind.Absolute));
    }

    // Set the screen name and display name if it differs
    if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(screen_name))
    {
        ScreenName.Text = screen_name;

        if (!screen_name.Equals(name))
        {
            _Name.Text = name;
        }
    }

    if (!string.IsNullOrEmpty(location))
    {
        Location.Text = location;
    }

    Tweets.Text = statuses_count.ToString() + " Tweets";
}

then the image will not render until another action forces a redraw (clicking a button) but the text controls will be updated. If within my callback function I call setImageFile(string imageFile) which is implemented as:

private void setImageFile(string imageFile)
{
    if (this.Dispatcher.CheckAccess())
    {
        ProfileImage.Source = new BitmapImage(new Uri("fdsfdfdsf.jpg", UriKind.Absolute));
    }
    else
    {
        this.Dispatcher.BeginInvoke(new Action<string>(setImageFile), imageFile);
    }
}

then the image will be rendered immediately. Why is this happening? What properties of the Dispatcher am I not fully understanding?


I strongly recommend that you not do this. SynchronizationObject was designed to handle this kind of scenario, along with AsyncOperation and AsyncOperationManager.

The only disadvantage to SynchronizationObject is that there isn't the ability to test whether the code is already running on the correct thread. That shouldn't be a problem, since business logic code should always be aware of its thread context.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜