简体   繁体   English

UI线程/调度程序问题(BeginInvoke)

[英]UI Thread/Dispatcher Issue (BeginInvoke)

In a previous question I asked how to get access to UI elements in a callback thread. 在上一个问题中,我询问了如何访问回调线程中的UI元素。 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 = (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: 如果在我的回调函数中,我将调用setImageFile(string imageFile),其实现为:

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 . 设计SynchronizationObject以及AsyncOperationAsyncOperationManager来处理这种情况。

The only disadvantage to SynchronizationObject is that there isn't the ability to test whether the code is already running on the correct thread. SynchronizationObject的唯一缺点是无法测试代码是否已经在正确的线程上运行。 That shouldn't be a problem, since business logic code should always be aware of its thread context. 这应该不成问题,因为业务逻辑代码应始终了解其线程上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM