我试图为我的WinForm项目中的多线程使用创建一个小类。
Tried Threads(UI问题),Backgroundworker(smth也出错了,现在就离开:)),现在尝试用 Task 类来做。但是现在,不能理解,如何为所有正在运行的任务创建一个不定式循环和一个取消方法(在课堂上)。 我发现的例子是用于1种方法。
所以,这是一个结构&当前工作部分的代码(在WinForm代码中使用的Worker.css和methonds)。
Worker.css
class Worker
{
public static int threadCount { get; set; }
public void doWork(ParameterizedThreadStart method)
{
Task[] tasks = Enumerable.Range(0, 4).Select(i => Task.Factory.StartNew(() => method(i))).ToArray();
}
}
用法 的 Form1.cs的
private void Start_btn_Click(object sender, EventArgs e)
{
Worker.threadCount = 1; //actually it doesn`t using now, number of tasks is declared in class temporaly
Worker worker = new Worker();
worker.doWork(Job);
string logString_1 = string.Format("Starting {0} threads...", Worker.threadCount);
log(logString_1);
}
public static int j = 0;
private void Job(object sender)
{
Worker worker = new Worker();
Random r = new Random();
log("Thread "+Thread.CurrentThread.ManagedThreadId +" is working...");
for (int i = 0; i < 5; i++)
{
j++;
log("J==" + j);
if (j == 50)
{
//worker.Stop();
log("STOP");
}
}
Thread.Sleep(r.Next(500, 1000));
}
所以,它运行了一个示例4个线程,它们执行了,我的日志中得到J == 20,没关系。
我的问题是,如何为 Worker.doWork()方法创建的任务实现不定循环。 并且还为Worker类创建一个.Stop()方法(它应该在调用时停止所有任务)。据我了解它是相关的问题,所以我把它放在1中。
我尝试了一些解决方案,但所有这些解决方案都基于 CancellationToken 用法,但我必须仅在Worker.doWork()方法内创建此元素,所以我不能使用用于创建Worker.Stop()方法的相同标记。
有人可以帮忙吗?我必须在这个软件中使用的线程数量范围约为5-200个线程。 使用 J 计算只是用于停止软件工作(停止任务/线程)的简单条件的一个示例。 实际上,停止条件主要类似于Queue&lt;&gt;。已完成,或列出&lt;&gt;元素是空的(完成)。
答案 0 :(得分:0)
最后,让它运作起来。
class Worker
{
public static int threadCount { get; set; }
Task[] tasks;
//ex data
public static string exception;
static CancellationTokenSource wtoken = new CancellationTokenSource();
CancellationToken cancellationToken = wtoken.Token;
public void doWork(ParameterizedThreadStart method)
{
try
{
tasks = Enumerable.Range(0, 4).Select(i => Task.Factory.StartNew(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
method(i);
}
}, cancellationToken)).ToArray();
}
catch (Exception ex) { exception = ex.Message; }
}
public void HardStop()
{
try
{
using (wtoken)
{
wtoken.Cancel();
}
wtoken = null;
tasks = null;
}
catch (Exception ex) { exception = ex.Message; }
}
}
但如果我使用此方法退出 cancellationToken.ThrowIfCancellationRequested(); 得到一个错误: 当 Job()方法达到J == 50,并且调用了worker.HardStop()函数时,程序窗口崩溃并且我得到并且异常“OparetionCanceledException未被用户代码处理” 在这个字符串上
cancellationToken.ThrowIfCancellationRequested();
所以,什么错了?我已经把它放在try {} catch(){} 据我所知,在wtoken.Cancel();中的任务(Task.IsCancelled == false,Task.IsFaulted == true)中应该更改一些布尔属性。
答案 1 :(得分:0)
我为此避免了所有的任务,并使用了Microsoft的Reactive Framework(NuGet&#34; Rx-Main&#34;)。
以下是:
var r = new Random();
var query =
Observable
.Range(0, 4, Scheduler.Default)
.Select(i =>
Observable
.Generate(0, x => true, x => x, x => x,
x => TimeSpan.FromMilliseconds(r.Next(500, 1000)),
Scheduler.Default)
.Select(x => i))
.Merge();
var subscription =
query
.Subscribe(i => method(i));
如果您想取消对方法的调用,请执行以下操作:
subscription.Dispose();
我已经对此进行了测试,它就像一种享受。
如果我将它包装在你的worker
课程中,那么它看起来像这样:
class Worker
{
private Random _r = new Random();
private IDisposable _subscription = null;
public void doWork()
{
_subscription =
Observable
.Range(0, 4, Scheduler.Default)
.Select(n =>
Observable
.Generate(
0, x => true, x => x, x => x,
x => TimeSpan.FromMilliseconds(_r.Next(500, 1000)),
Scheduler.Default)
.Select(x => n))
.Merge()
.Subscribe(i => method(i));
}
public void HardStop()
{
_subscription.Dispose();
}
}