c# - C# WFA - 将耗时的工作委托给另一个线程
问题描述
我想在 C# (WFA) 中创建一些机制,允许我在运行中向一个特定的分离线程添加一些函数。
public class MyClass
{
private Thread specialThread = new Thread();
MyClass()
{
regularMethod();
specialThread.AddNextJob( veryLongTimeConsumingMethod() );
//....
anotherUseMethod();
}
private void veryLongTimeConsumingMethod()
{
//...time consuming database, logic, etc...
this.UIThread(delegate ()
{
control1.Items = updatedItems;
});
}
private void anotherUseMethod()
{
//...another method wants to do a long job
specialThread.AddNextJob(veryLongTimeConsumingMethod());
}
}
在所有“工作”完成后,我希望“特殊线程”处于“待机”状态(等待另一个“工作”)。我需要按顺序完成所有“工作”。有没有常见的方法来实现这一点?
解决方案
我前一阵子写过这样的东西。现在你可能会使用 async await 来让东西在后台线程上运行。但这是我写的一个快速任务队列。
public class TaskQueue
{
public Queue<Task> CurrentTasks { get; private set; }
public bool TaskQueueRunning { get; private set; }
public TaskQueue()
{
CurrentTasks = new Queue<Task>();
TaskQueueRunning = false;
}
public void AddTask(Task task)
{
CurrentTasks.Enqueue(task);
ProcessTasks();
}
private void ProcessTasks()
{
if (!TaskQueueRunning)
{
TaskQueueRunning = true;
ProcessIndividualTask();
}
}
private void ProcessIndividualTask()
{
if (CurrentTasks.Count > 0)
{
TaskItem currenttask = CurrentTasks.Dequeue();
currenttask.CurrentTask.ContinueWith(x => ProcessIndividualTask());
currenttask.CurrentTask.Start();
}
else
{
TaskQueueRunning = false;
}
}
}
你在你的主窗体上实例化它:
private TaskQueue backgroundtasks = new TaskQueue();
然后,当您想在后台线程上执行方法时,您将其包装在任务中。例如
Task newtask = new Task(() => MyMethodCall());
backgroundtasks.AddTask(newtask);
或者,如果您想内联整个内容:
backgroundtasks.AddTask(new Task(() => MyMethodCall()));
如果任务队列上没有项目,则队列将不会运行,如果添加项目,队列将运行。如果在第一个任务完成时添加多个项目,它将ContinueWith
是下一个任务。任务将始终按顺序运行,因为底层类型是队列,并且只有在当前任务完成后才会运行下一个任务。
这样做的一个限制是您的任务无法返回结果。不过,您可以设置一个任务来写入变量。例如
Task newtask = new Task(() => {
myvar = MyMethodCall();
});
backgroundtasks.AddTask(newtask);
这假设您的主窗体上有一个名为 myvar 的属性/变量。但是要小心这一点,因为如果您从不同的任务多次写入同一个变量,您将无法预测任何时候该值是什么 - 特别是如果您从不同的线程访问它。谈到跨线程 - 这里没有防护,所以要特别小心。
建议您研究 Async 和 Await,因为您可能会发现它们更适合您想要做的事情。
推荐阅读
- azure-devops - 触发另一个管道并设置变量
- amazon-web-services - 使用 sigv4 插件来自 Flutter 的 AWS Polly 请求
- istio - 安装期间的 Istio-ingressgateway 自定义
- node.js - How to run a function after a given time in node.JS?
- cuda - 如何使用 Thrust 中的一些预定义序列对向量进行排序
- mysql - Laravel 8 SQLSTATE [HY000] [1045] 用户'forge'@'localhost'的访问被拒绝(使用密码:否)
- powershell - 如果匹配模式后跟下一个模式与power shell中的计数不匹配,则要求添加4行
- html - 如何在 Mapbox gl js 中使用 AWS S3 光栅文件?
- java - java synchronized 无法同步
- angular - .NET Core 3.0 Web Api 和 Angular 10 应用程序可以托管在同一个 AWS EC2 Ubuntu 实例上吗?