C# 多线程方法

C# 多线程方法,c#,multithreading,C#,Multithreading,我已经使用TPL开发了下面的代码,除了如何重新启动任务外,所有代码都可以正常工作。当前,当我单击button1时,线程从textBox1开始,类似地,从button3和textBox2开始。当我单击button3和button4时,两个线程都被取消 现在,我想重新启动button1和button3的单击事件中停止的线程。我尝试了很多方法,但都不知道如何做到这一点 代码如下: public partial class Form1 : Form { CancellationTokenSour

我已经使用TPL开发了下面的代码,除了如何重新启动任务外,所有代码都可以正常工作。当前,当我单击
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等提供的。