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