gpt4 book ai didi

c# - 非 Win Form C# 应用程序中的同步事件处理程序线程执行

转载 作者:行者123 更新时间:2023-11-30 20:05:54 26 4
gpt4 key购买 nike

我正在一个接一个地运行多个时间\CPU 密集型进程(TimeExpensive 类型)。主线程 (A) 在另一个线程 (B) 中异步启动 TimeExpensive 进程并变为非事件状态。完成时,线程 B 同步触发调用者的完成处理程序,并在线程 B 中启动下一个 TimeExpensive 进程。创建了一个新线程 (C),但在启动 C 之后,B 完成。因此,对于 n 个进程,将创建 n 个线程,并且大多数时候,它们不会共存。

人们可能希望它以线性单线程方式实现,但 TimeExpensive 是由第三方实现的,并且在运行时会使用所有系统核心并运行数小时。

//This will run as console app 
class Program
{
static void Main(string[] args)
{
new Program().StartJobs();
}

void StartJobs()
{
Main mainJob = new Main();
mainJob.MainCompletionEvent +=
new Action<object, EventArgs>(mainJob_MainCompletionEvent);
mainJob.Start();
}

void mainJob_MainCompletionEvent(object sender, EventArgs e)
{
//if(success) Environment.Exit(0);
}

}

class Main
{
int processCounter = 0;
public event Action<object, EventArgs> MainCompletionEvent;
public void Start()
{
//...do other important tasks here...
processCounter++;
TimeExpensive te = new TimeExpensive();
te.CompletionEvent += new Action(TimeExpensive_CompletionHandler);
Thread aThread = new Thread(te.Run);
aThread.IsBackground = false;
aThread.Name = "TimeExpensive Thread: " + processCounter;
aThread.Start();
}

void TimeExpensive_CompletionHandler()
{
Console.WriteLine("current Thread Name: " + Thread.CurrentThread.Name);
//Start another Process In Background if
if (processCounter < 5)
{
Start();
}
else
{
Console.ReadKey();
if (JobCompletionEvent != null)
JobCompletionEvent(this, new EventArgs());
}
}
}

class TimeExpensive
{
public event Action CompletionEvent;

public void Run()
{
//doing time expensive task
//...

//when finish Notify completion Handler...
if (CompletionEvent != null)
{
CompletionEvent();
}
}
}

//Output
current Thread Name: TimeExpensive Thread: 1
current Thread Name: TimeExpensive Thread: 2
current Thread Name: TimeExpensive Thread: 3
current Thread Name: TimeExpensive Thread: 4
current Thread Name: TimeExpensive Thread: 5

上面的实现模仿了我描述的行为。困扰我的是事件处理程序同步运行,直到下一个线程启动,在此期间,它正在执行许多不是为它设计的任务。

不确定这是否好,有没有办法让我在线程 B 的完成处理程序中返回到线程 A?还是我应该更好地使用另一个 delegate.BeginInvoke 开始事件处理程序执行?

我希望用简单而安全的方法来做到这一点。任何帮助是极大的赞赏。

P.S 我读了很多帖子,但没有人能很好地处理这种情况。

编辑

添加静态 main 以显示如何在控制台应用程序中启动此代码。请记住,还可以创建 UI 来启动“Main”作业。它肯定会创建 BackgroundWorker 线程来创建 mainJob 对象并运行它。谢谢!

最佳答案

Is there a way I can go back to thread A while in Thread B's completion handler?

不,您没有适当的管道来编码从一个线程到另一个线程的调用。这种管道由 GUI 应用程序的主线程提供。出于必要,用户界面基本上是线程不安全的。支持此类编码的 UI 线程有多个实现细节。它在 producer/consumer 的典型实现中充当消费者线程模型。

这需要一个线程安全的队列和一个读取队列的消费者循环。您可能将其识别为 Windows GUI 应用程序中的消息队列。使用调用 GetMessage 以读取通知并对其执行操作的消息循环。编码调用现在很简单,您只需将消息发布到消息队列,UI 线程读取它并执行请求。发布由 Winforms 的 Control.BeginInvoke 和 WPF 的 Dispatcher.BeginInvoke 实现。

您当然可以自己实现这种同步机制。 .NET 4 BlockingCollection 类使它变得简单。但确实请记住,您必须从根本上改变线程 A 的执行方式。对发布到队列的请求保持响应很重要。像 BackgroundWorker 这样的类试图解决的问题。请记住,GUI 消息循环的存在是因为它是必需的,UI 不是线程安全的。控制台应用程序(通常)没有相同类型的负担,控制台是线程安全的。

关于c# - 非 Win Form C# 应用程序中的同步事件处理程序线程执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10444668/

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