C#/WPF - 我无法从后台工作人员更新 UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18030759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:21:36  来源:igfitidea点击:

C#/WPF - I can't update UI from a backgroundworker

c#wpfmultithreadingbackgroundworkerui-thread

提问by Alaa Salah

I have a code that fetches tweets from a specific Twitter account using Tweetsharplibrary, creates instance of a custom UserControland post tweet text to that UserControlthen add it to a StackPanel.

我有一个使用Tweetsharp库从特定 Twitter 帐户获取推文的代码,创建自定义实例并将推UserControl文文本发布到该实例,UserControl然后将其添加到StackPanel.

However, I have to get a lot of tweets and it seems that the application would freeze while adding user controls to the StackPanel. I tried using BackgroundWorker, but I wasn't lucky until now.

但是,我必须收到很多推文,而且在向StackPanel. 我尝试使用BackgroundWorker,但直到现在我都不走运。

My code :

我的代码:

private readonly BackgroundWorker worker = new BackgroundWorker();

// This ( UserControl ) is used in the MainWindow.xaml
private void UserControl_Loaded_1(object sender, RoutedEventArgs e)
{
    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    worker.RunWorkerAsync();
}

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    int usrID;

    var service = new TwitterService(ConsumerKey, ConsumerSecret);
    service.AuthenticateWith(AccessToken, AccessTokenSecret);
    ListTweetsOnUserTimelineOptions options = new ListTweetsOnUserTimelineOptions();
    options.UserId = usrID;
    options.IncludeRts = true;
    options.Count = 10;
    twitterStatuses = service.ListTweetsOnUserTimeline(options);
}

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    try
    {
        foreach (var item in twitterStatuses)
        {
            TweetViewer tweetViewer = new TweetViewer(); // A UserControl within another UserControl
            tweetViewer.Tweet = item.Text;
            tweetViewer.Username = "@stackoverflow";
            tweetViewer.RealName = "Stack Overflow"
            tweetViewer.Avatar = ImageSourcer(item.Author.ProfileImageUrl);
            stackPanel.Children.Add(tweetViewer);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

}

What I want to do now is to solve the problem of not being able to perform the code contained in worker_RunWorkerCompletedwithin a BackgroundWorkerbut every time I try to perform it using a BackgroundWorkerit fails & gives me errors like :

我现在想要做的是解决无法在a内执行worker_RunWorkerCompleted中包含的代码的问题,BackgroundWorker但每次我尝试使用 a 执行它时,BackgroundWorker它都会失败并给我类似的错误:

The calling thread must be STA, because many UI components require this.

调用线程必须是 STA,因为许多 UI 组件都需要它。

I tried also using a STA System.Threading.Threadinstead of the BackgroundWorker but without luck!

我也尝试使用STA System.Threading.Thread而不是 BackgroundWorker 但没有运气!

What am I missing ? I'm really new to WPF and I may be ignoring something important.

我错过了什么?我对 WPF 真的很陌生,我可能会忽略一些重要的事情。

回答by glautrou

You get this exception because your background worker uses a new thread, and this thread is different than the main UI thread. To simplify the error message says that you cannot change your UI element from another thread, they are independant.

你得到这个异常是因为你的后台工作线程使用了一个新线程,而这个线程与主 UI 线程不同。为了简化错误消息说您不能从另一个线程更改您的 UI 元素,它们是独立的。

This answerwill solve your problem.

这个答案将解决您的问题。

I also found this answerfrom @Marc Gravell

我还从@Marc Gravell找到了这个答案

///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
    someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files