gpt4 book ai didi

c# - Dispatcher.Dispatch 在 UI 线程上

转载 作者:太空狗 更新时间:2023-10-30 00:08:19 28 4
gpt4 key购买 nike

我对何时使用 Dispatcher.Invoke 从不同线程更新 UI 上的某些内容存有疑问。

这是我的代码...

public Window4()
{
InitializeComponent();
this.DataContext = this;

Task.Factory.StartNew(() => Test() );
}

private List<string> listOfString = new List<string>();

public List<string> ListOfString
{
get { return listOfString; }
set { listOfString = value; }
}

public void Test()
{
listOfString.Add("abc");
listOfString.Add("abc");
listOfString.Add("abc");
}

<Grid>
<ListView ItemsSource="{Binding ListOfString}" />
</Grid>

我在不同的线程上开始一个新任务,我需要使用 Dispatcher.BeginInvoke 来更新 UI。

在这种情况下,它正在更新 UI,但我见过一些情况,人们使用来自不同线程的 Dispatcher.Invoke 或 BeginInvoke 更新 UI。

所以我的问题是我们什么时候必须这样做以及为什么在这种情况下它工作正常。

感谢和问候,巴维克

最佳答案

I have the doubt regarding when to use the Dispatcher.Invoke to update something on UI from different Thread.

当您在不同的线程上时,您将始终必须使用调度程序来更新属于另一个线程的 ui 组件。

I am starting a new Task on the different Thread, do i need to use Dispatcher.BeginInvoke to update the UI.

任务允许在不阻塞调用它们的线程的情况下执行多个操作,但这并不意味着它们在不同的线程上。但是,当从任务内部更新 UI 时,您将需要使用调度程序。

In this case it is updating the UI, but i've seen some scenarios where people update UI using Dispatcher.Invoke or BeginInvoke from the different Thread.

Invoke 将在执行操作时阻塞调用线程,而 BeginInvoke 则不会。 BeginInvoke 会立即将控制权返回给调用者,Invoke 可能会导致调用线程在执行繁重操作时挂起。

这是来自msdn文档,

In WPF, only the thread that created a DispatcherObject may access that object. For example, a background thread that is spun off from the main UI thread cannot update the contents of a Button that was created on the UI thread. In order for the background thread to access the Content property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread. This is accomplished by using either Invoke or BeginInvoke. Invoke is synchronous and BeginInvoke is asynchronous.

编辑:为了回应您的评论,我进行了一些测试。

当从一个任务调用 Test() 时(不使用调度程序)我得到这个错误“调用线程无法访问这个对象,因为另一个线程拥有它。”

所以我创建了一个名为 PrintThreadID() 的方法。我在进入任务之前打印线程,然后从任务内部打印线程,它确实报告两者都在 同一线程 ID 上运行。

该错误具有误导性,因为它表示调用线程与拥有它的线程不同,而 PrintThreadID() 函数显示这不是真的,它们实际上在同一个线程上。如果不使用 Dispather.Invoke(),同一线程上的任务仍然无法更新 UI 组件。

所以这是一个工作示例,它将从任务更新网格。


public partial class MainWindow : Window
{
public List<string> myList { get; private set; }

public MainWindow()
{
InitializeComponent();
myList = new List<string>();
label1.Content = Thread.CurrentThread.ManagedThreadId.ToString();

Task.Factory.StartNew(PrintThreadID);
Task.Factory.StartNew(Test);

}

private void PrintThreadID()
{
label1.Dispatcher.Invoke(new Action(() =>
label1.Content += "..." + Thread.CurrentThread.ManagedThreadId.ToString()));
}

private void Test()
{
myList.Add("abc");
myList.Add("abc");
myList.Add("abc");

// if you do not use the dispatcher you will get the error "The calling thread cannot access this object because a different thread owns it."


dataGrid1.Dispatcher.Invoke(new Action(() =>
{
dataGrid1.ItemsSource = myList.Select(i => new { Item = i });
}));
}
}

关于c# - Dispatcher.Dispatch 在 UI 线程上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9980053/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com