C# 多线程方法
我已经使用TPL开发了下面的代码,除了如何重新启动任务外,所有代码都可以正常工作。当前,当我单击C# 多线程方法,c#,multithreading,C#,Multithreading,我已经使用TPL开发了下面的代码,除了如何重新启动任务外,所有代码都可以正常工作。当前,当我单击button1时,线程从textBox1开始,类似地,从button3和textBox2开始。当我单击button3和button4时,两个线程都被取消 现在,我想重新启动button1和button3的单击事件中停止的线程。我尝试了很多方法,但都不知道如何做到这一点 代码如下: public partial class Form1 : Form { CancellationTokenSour
button1
时,线程从textBox1
开始,类似地,从button3
和textBox2
开始。当我单击button3
和button4
时,两个线程都被取消
现在,我想重新启动button1
和button3
的单击事件中停止的线程。我尝试了很多方法,但都不知道如何做到这一点
代码如下:
public partial class Form1 : Form
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken token;
CancellationTokenSource cancellationTokenSource1 = new CancellationTokenSource();
CancellationToken token1;
public Form1()
{
InitializeComponent();
token = cancellationTokenSource.Token;
token1 = cancellationTokenSource1.Token;
}
private void button1_Click(object sender, EventArgs e)
{
Task t = Task.Factory.StartNew(() =>
{
var run = true;
while (run)
{
for (int i = 0; i < 100; i++)
{
if (token.IsCancellationRequested)
{
run = false;
break;
//token.ThrowIfCancellationRequested();
}
// your code
System.Threading.Thread.Sleep(1000);
Action act = () => textBox1.Text = Convert.ToString(i);
textBox1.Invoke(act);
}
}
});
}
private void button2_Click(object sender, EventArgs e)
{
cancellationTokenSource.Cancel();
}
private void button3_Click(object sender, EventArgs e)
{
Task t1 = Task.Factory.StartNew(() =>
{
var run = true;
while (run)
{
for (int i = 0; i < 100; i++)
{
if (token1.IsCancellationRequested)
{
run = false;
break;
//token1.ThrowIfCancellationRequested();
}
// your code
System.Threading.Thread.Sleep(1000);
Action act = () => textBox2.Text = Convert.ToString(i);
textBox2.Invoke(act);
}
}
});
}
private void button4_Click(object sender, EventArgs e)
{
cancellationTokenSource1.Cancel();
}
}
公共部分类表单1:表单
{
CancellationTokenSource CancellationTokenSource=新的CancellationTokenSource();
取消令牌;
CancellationTokenSource cancellationTokenSource1=新的CancellationTokenSource();
取消令牌1;
公共表格1()
{
初始化组件();
令牌=cancellationTokenSource.token;
token1=cancellationTokenSource1.Token;
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
Task t=Task.Factory.StartNew(()=>
{
var-run=true;
while(运行)
{
对于(int i=0;i<100;i++)
{
if(令牌.IsCancellationRequested)
{
运行=错误;
打破
//token.ThrowIfCancellationRequested();
}
//你的代码
系统线程线程睡眠(1000);
Action act=()=>textBox1.Text=Convert.ToString(i);
textBox1.调用(act);
}
}
});
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
cancellationTokenSource.Cancel();
}
私有无效按钮3\u单击(对象发送者,事件参数e)
{
任务t1=任务.Factory.StartNew(()=>
{
var-run=true;
while(运行)
{
对于(int i=0;i<100;i++)
{
if(令牌1.IsCancellationRequested)
{
运行=错误;
打破
//token1.ThrowIfCancellationRequested();
}
//你的代码
系统线程线程睡眠(1000);
Action act=()=>textBox2.Text=Convert.ToString(i);
textBox2.调用(act);
}
}
});
}
私有无效按钮4_单击(对象发送者,事件参数e)
{
cancellationTokenSource1.Cancel();
}
}
您需要使用信号同步线程,通常使用AutoResetEvent、ManualReset和CountdownEvent等方法来实现。您可以通过以下方式实现这一点
声明手动重置事件:
CancellationTokenSource cancellationTokenSource1 = new CancellationTokenSource();
CancellationToken token1;
private ManualResetEvent mre = new ManualResetEvent(false);
根据取消请求修改
if (token.IsCancellationRequested) {
run = false;
mre.WaitOne();
//token.ThrowIfCancellationRequested();
}
OnStart/OnResume:
mre.Set()代码>您不能使用TPL暂停任务,您只能取消。如果要暂停,则需要向任务内的代码添加某种信号事件,以便您可以将其标记为停止执行并等待重置,例如查看AutoResetEvent
类或类似内容。但是,请注意,如果用户生成几百个任务,那么整个应用程序将变得相当缓慢。任务不是线程,而是任务。有一件事需要在后台运行。如果你想运行很多东西,你需要使用很多任务。不要像线程一样在任务内部使用无限循环,而是使用task.Run
创建任务,无论何时需要执行某些操作。顺便说一句,也不需要使用Invoke。只需将方法转换为async
并使用wait
。wait之后的方法将在UI线程上运行,并能够直接更新文本框。您想做什么?显然,这是演示代码。问题是它滥用了任务。您可以使用计时器执行相同的操作,也可以使用等待任务执行循环。延迟(1000,令牌)
并在按钮1\u点击
中删除几乎所有的代码。任务不会暂停或重新启动-它们表示将在单个线程池线程上运行的短作业。如果TPL使用正确,则无需使用同步。一个任务可以通过ContinueWith
或wait
一个接一个地运行。不是一种方式-如果必须同步,则是错误的。任务是单个作业,而不是线程。OP(ab)使用任务并将其视为ThreadsBeasides,如果要使用事件,为什么要使用取消令牌?你不会取消的。您使用的是表示“取消”的内容,用于完全不同的应用程序job@PanagiotisKanavos没错,我只是相信OP是在试验和探索他的命名惯例,而不是命名惯例。这完全是对任务的滥用。taks应该是短的,不包含无限循环。它不需要额外的同步,这是由ContinueWith、wait等提供的。