gpt4 book ai didi

c# - 如何让父线程等待子线程完成 - C#

转载 作者:太空宇宙 更新时间:2023-11-03 20:02:30 26 4
gpt4 key购买 nike

我正在运行一个后台线程来从数据库中获取数据,这样当前线程 (UI) 就不会卡住。我正在使用 TPL 来实现这一目标。

List<string> _myList1, _myList2;
private void LoadCollections(){
Task db_task = new Task(() => CallDB());
var continuations = db_task.ContinueWith((ant) =>
{
_myList1 = GetDataFromMetaData1();
_myList2 = GetDataFromMetaData2();
});

db_task.Start();
LoadTemplates(); //execute only after 'db_task' completes execution
}

在上面的代码中

CallDB() - 从数据库中获取数据并将其存储在元数据中。在这种情况下,将其视为字符串列表。 (比如 List<string> MetaStrings)

GetDataFromMetaData1()GetDataFromMetaData2() - 获取 2 个单独的列表,它们是 MetaStrings 的子列表.

现在我想执行函数LoadTemplates仅在 _myList1 之后和 _myList2被加载,即当db_task已经执行完毕。目前,我正在使用这个

while(_mylist1==null && _mylist2==null)
Thread.Sleep(50);

LoadTemplates();

但这显然会卡住 UI,因为 UI 线程会进入休眠状态。那么有人可以建议一种有效的方法来处理这种情况吗?

附言:LoadTemplates()初始化一些 ObservableCollection变量。如果LoadTemplates()在子线程内部被调用,db_task然后抛出以下错误This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread .于是就出现了线程等待的场景。

最佳答案

你问错了问题。在辅助线程上运行进程时,您绝不会希望主线程等待操作完成。那只是一种浪费……您还不如在主线程上运行该操作并完成它。

因此,问题是:如何让主(父)线程处理辅助(子)线程的完成?

根据您收到的错误消息,您似乎是使用 WPF 编写的。这意味着您应该提出的问题的一个答案是您从响应辅助线程完成的事件处理程序调用 Dispatcher.Invoke。

正如 Terry 所建议的,您可以使用 async/await 功能。例如,这可能有效(如果没有完整的代码示例很难说):

List<string> _myList1, _myList2;
private async void LoadCollections(){
Task db_task = new Task(() => CallDB());

var continuations = db_task.ContinueWith((ant) =>
{
_myList1 = GetDataFromMetaData1();
_myList2 = GetDataFromMetaData2();
});

db_task.Start();

await continuations;

LoadTemplates(); //execute only after 'db_task' completes execution
}

换句话说,继续像现在一样安排任务,但使用 async 和 await 进行设置,以便仅在延续完成后调用 LoadTemplates()(这反过来不会执行直到初始 DB 任务完成),特别是 LoadTemplates() 在首先调用 LoadCollections 的主 Dispatcher 线程中执行。

请注意,理想情况下,LoadCollections 的返回类型实际上是 Task。编译器更喜欢这个,它可以让你更好地处理可能出现的异常。但是 void 应该没问题,并且在处理事件处理程序方法时并不少见。

编辑:我还想提一下,一种涉及更彻底地更改代码但恕我直言更符合异步/等待模式的替代方法是简单地等待原始 db_task 然后执行“继续”语句内联(即不在任务中),或者(如果这些语句本身是长时间运行的并且应该在后台执行)仍然等待原始任务然后也等待继续作为他们自己的任务而不是明确地作为继续数据库任务。

例如(假设继续操作很简短并且可以在主线程上运行):

List<string> _myList1, _myList2;
private async void LoadCollections(){
await Task.Run(() => CallDB());

_myList1 = GetDataFromMetaData1();
_myList2 = GetDataFromMetaData2();

LoadTemplates(); //execute only after 'db_task' completes execution
}

关于c# - 如何让父线程等待子线程完成 - C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26456486/

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