C# 对多线程应用程序中的按钮单击没有影响

C# 对多线程应用程序中的按钮单击没有影响,c#,multithreading,winforms,C#,Multithreading,Winforms,除了“停止”按钮外,其他一切都正常。(再次单击按钮3和按钮4): 我做了一个有四个按钮的应用程序 它是一个多线程应用程序 按钮1和2将开始生成线程 按钮3和4将分别停止该过程 但它似乎不起作用 这是我的密码: public partial class Form1: Form { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken tok

除了“停止”按钮外,其他一切都正常。(再次单击按钮3和按钮4):

我做了一个有四个按钮的应用程序

它是一个多线程应用程序

按钮1和2将开始生成线程

按钮3和4将分别停止该过程

但它似乎不起作用

这是我的密码:

public partial class Form1: Form
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    CancellationToken token;

    public Form1()
    {
        InitializeComponent();
        token = cancellationTokenSource.Token;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Task t = Task.Run(() =>
        {
            while (true)
            {
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    Action act = () => textBox1.Text = Convert.ToString(i);
                    textBox1.Invoke(act);
                }
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                } 
            }
        }, token);
        }

    private void button2_Click(object sender, EventArgs e)
    {
        //token.Cancel();
    }

    private void button3_Click(object sender, EventArgs e)
    {
        Task t1 = Task.Run(() =>
        {
            while (true)
            {
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    Action act = () => textBox2.Text = Convert.ToString(i);
                    textBox2.Invoke(act);
                }
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                } 
            }
        }, token);
    }

    private void button4_Click(object sender, EventArgs e)
    {
        //token.Cancel();
    }
}
公共部分类表单1:表单
{
CancellationTokenSource CancellationTokenSource=新的CancellationTokenSource();
取消令牌;
公共表格1()
{
初始化组件();
令牌=cancellationTokenSource.token;
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
Task t=Task.Run(()=>
{
while(true)
{
对于(int i=0;i<100;i++)
{
系统线程线程睡眠(1000);
Action act=()=>textBox1.Text=Convert.ToString(i);
textBox1.调用(act);
}
if(令牌.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
} 
}
},代币);
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
//token.Cancel();
}
私有无效按钮3\u单击(对象发送者,事件参数e)
{
任务t1=任务。运行(()=>
{
while(true)
{
对于(int i=0;i<100;i++)
{
系统线程线程睡眠(1000);
Action act=()=>textBox2.Text=Convert.ToString(i);
textBox2.调用(act);
}
if(令牌.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
} 
}
},代币);
}
私有无效按钮4_单击(对象发送者,事件参数e)
{
//token.Cancel();
}
}
更新

以下是更新的代码:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MultiThreading_Start_Stop_Counter
{
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.Run(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                if (token.IsCancellationRequested)
                {
                    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.Run(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                if (token1.IsCancellationRequested)
                {
                    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();
    }
}
}
使用系统;
使用系统线程;
使用System.Threading.Tasks;
使用System.Windows.Forms;
名称空间多线程\u开始\u停止\u计数器
{
公共部分类Form1:Form
{
CancellationTokenSource CancellationTokenSource=新的CancellationTokenSource();
取消令牌;
CancellationTokenSource cancellationTokenSource1=新的CancellationTokenSource();
取消令牌1;
公共表格1()
{
初始化组件();
令牌=cancellationTokenSource.token;
token1=cancellationTokenSource1.Token;
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
Task t=Task.Run(()=>
{
对于(int i=0;i<10;i++)
{
if(令牌.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
//你的代码
系统线程线程睡眠(1000);
Action act=()=>textBox1.Text=Convert.ToString(i);
textBox1.调用(act);
}
});
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
cancellationTokenSource.Cancel();
}
私有无效按钮3\u单击(对象发送者,事件参数e)
{
任务t1=任务。运行(()=>
{
对于(int i=0;i<10;i++)
{
if(令牌1.IsCancellationRequested)
{
token1.ThrowIfCancellationRequested();
}
//你的代码
系统线程线程睡眠(1000);
Action act=()=>textBox2.Text=Convert.ToString(i);
textBox2.调用(act);
}
});
}
私有无效按钮4_单击(对象发送者,事件参数e)
{
cancellationTokenSource1.Cancel();
}
}
}
现在任务正在取消,但有以下例外情况:

mscorlib.dll中发生“System.OperationCanceledException”类型的异常,但未在用户代码中处理 其他信息:操作已取消

已解决:

使用while循环。谢谢大家!

  • Cancel方法属于CancellationTokenSource,所以不能在CancellationToken上调用它
  • 如果(token.IsCancellationRequested)仅在100秒后调用,那么可能是因为您没有等待足够长的时间,或者更可能是将支票放在了错误的位置

    • 正如@Roman所说

      如果在不同的任务中请求令牌,则应为每个
      取消令牌
      创建一个新的
      取消令牌源

      CancellationTokenSource cancellationTokenSource1, cancellationTokenSource2;
      CancellationToken token1, token2;
      
      制作两个不同的
      CancellationTokenSource
      CancellationToken

      根据您的取消情况,在for循环或while循环中使用它们,如下所示

      for (int i = 0; i < 100; i++)
      {
          if (token1.IsCancellationRequested)
          {
              token1.ThrowIfCancellationRequested();
          }
          // your code
          System.Threading.Thread.Sleep(1000);
          Action act = () => textBox1.Text = Convert.ToString(i);
          textBox1.Invoke(act);
      }
      

      检查令牌是否被取消的部分应该放在for循环中

      for (int i = 0; i < 100; i++)
      {
           if (token.IsCancellationRequested)
           {
               token.ThrowIfCancellationRequested();
           }
           System.Threading.Thread.Sleep(1000);
           Action act = () => textBox1.Text = Convert.ToString(i);
           textBox1.Invoke(act);
      }
      
      for(int i=0;i<100;i++)
      {
      if(令牌.IsCancellationRequested)
      {
      token.ThrowIfCancellationRequested();
      }
      系统线程线程睡眠(1000);
      Action act=()=>textBox1.Text=Convert.ToString(i);
      textBox1.调用(act);
      }
      
      另外,您抛出OperationCanceledException并没有捕获它

      如果不想处理异常,可以为while循环引入一些变量,如:

      Task t = Task.Run(() =>
              {
                  var run = true;
                  while (run)
                  {
                      for (int i = 0; i < 100; i++)
                      {
                          if (token.IsCancellationRequested)
                          {
                              run = false;
                              break;
                          }
                         //loop code
                      } 
                  }
              }, token);
      
      Task t=Task.Run(()=>
      {
      var-run=true;
      while(运行)
      {
      对于(int i=0;i<100;i++)
      {
      if(令牌.IsCancellationRequested)
      {
      运行=错误;
      打破
      }
      //循环码
      } 
      }
      },代币);
      
      button2应包含取消令牌cancellationTokenSource.cancel()的代码
      Task t = Task.Run(() =>
              {
                  var run = true;
                  while (run)
                  {
                      for (int i = 0; i < 100; i++)
                      {
                          if (token.IsCancellationRequested)
                          {
                              run = false;
                              break;
                          }
                         //loop code
                      } 
                  }
              }, token);