C# 在C语言中取消任务#
我有一个有两个按钮的表单(开始,停止) 当我按下开始按钮时,任务将被初始化,并调用一个函数,该函数将一直运行直到按下停止按钮 但当我按下“停止”按钮时,窗体冻结。为什么? 我已经从中复制了代码段,但它仍然冻结了表单。 那么,告诉我如何正确地取消任务C# 在C语言中取消任务#,c#,C#,我有一个有两个按钮的表单(开始,停止) 当我按下开始按钮时,任务将被初始化,并调用一个函数,该函数将一直运行直到按下停止按钮 但当我按下“停止”按钮时,窗体冻结。为什么? 我已经从中复制了代码段,但它仍然冻结了表单。 那么,告诉我如何正确地取消任务 public partial class Form1 : Form { private readonly CancellationTokenSource _cts = new CancellationTokenSource(); pr
public partial class Form1 : Form
{
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private Task _task;
public Form1()
{
InitializeComponent();
}
//Funtion that runs when Task is initialized.
private void EventLoop(CancellationToken token)
{
//Code here..
while (!token.IsCancellationRequested)
{
//Code here..
}
if (token.IsCancellationRequested)
{
MessageBox.Show("Operation Complete..!!");
}
}
//Function for Start Button.
private void Start_Click(object sender, EventArgs e)
{
_task = Task.Factory.StartNew(() => EventLoop(_cts.Token), _cts.Token);
}
//Function for Stop button.
private void Stop_Click(object sender, EventArgs e)
{
_cts.Cancel();
}
}
MSDN中的类似示例:
var compute = Task.Factory.StartNew(() =>
{
return SumRootN(j);
}, tokenSource.Token);`
按下停止按钮后形成。
token.IsCancellationRequested
为true
完整的EventLoop()
函数
private void EventLoop(CancellationToken token)
{
SerialPort sp = new SerialPort();
string text, batch, part, courseName;
text = batch = part = courseName = "";
int courseId = 0;
this.Invoke((MethodInvoker)delegate()
{
text = portCB.SelectedItem.ToString();
batch = comboBox2.SelectedItem.ToString();
part = comboBox3.SelectedItem.ToString();
courseName = comboBox1.SelectedItem.ToString();
progressBar1.Value = 20;
using (Model1 db = new Model1())
{
courseId = db.Courses.Where(c => c.Course_name.ToUpper() == courseName.ToUpper()).Select(c => c.Course_Id).Single();
}
});
sp.PortName = text;
sp.BaudRate = 9600;
sp.Open();
while (!token.IsCancellationRequested)
{
text = sp.ReadLine();
if (text.Contains("Found ID #"))
{
this.Invoke((MethodInvoker)delegate()
{
textBox2.Clear();
textBox2.Text = "Getting Registation ID.\n";
progressBar1.Value = 60;
});
string splitText = text.Split('#')[1];
int end = splitText.IndexOf(' ');
int id = int.Parse(splitText.Substring(0, end));
using (Model1 db = new Model1())
{
var result = db.Students.Where(s => s.Reg_Id == id && s.Batch == batch && s.Class == part).Select(s => s).SingleOrDefault();
if (result != null)
{
Attendance a = new Attendance();
a.Course_Id = courseId;
a.Student_Id = id;
a.Status = "P";
a.Date = DateTime.Today.Date;
a.Batch = batch;
a.Part = part;
db.Attendances.Add(a);
string message = "";
if (db.SaveChanges() != 0)
{
message = "Attendance Uploaded..!!\n";
}
else
{
message = "Attendance Not Uploaded ..!!\n";
}
this.Invoke((MethodInvoker)delegate()
{
progressBar1.Value = 100;
textBox2.AppendText(message);
});
}
else
{
this.BeginInvoke((MethodInvoker)delegate()
{
textBox2.AppendText("Student Does not belong to Specified Batch Or Part..\n");
});
}
}
}
else
{
this.Invoke((MethodInvoker)delegate()
{
textBox2.AppendText("No Match Found..!! \n");
});
}
this.Invoke((MethodInvoker)delegate()
{
textBox1.AppendText(text + "\n");
});
}
sp.Close();
// This exception will be handled by the Task
// and will not cause the program to crash
if (token.IsCancellationRequested)
{
//MessageBox.Show("Operation Comptele..!!");
}
}
您可以调用
MessageBox.Show(“操作完成..!!”代码>正在取消。强烈建议不要这样做,不要说您正在从UI线程以外的其他位置调用UI操作
注释MessageBox.Show(“操作完成..!!”)代码>行输出
*编辑*
问题作者对其原始问题的评论发现了错误,从帖子中删除了哪一行。以下是我的结论:
始终尝试隔离问题,并以最纯粹的形式重现。在此过程中,您可能会诊断并发现问题本身:-)
因此,如果有问题的代码需要发布很长时间,那么绝对不是删除行然后发布的方式。方法是删除行并查看问题是否存在,换句话说:以最纯粹的可复制形式隔离问题请在任务中使用异步调用
private async void Start_Click(object sender, EventArgs e)
{
_task = Task.Factory.StartNew(() => EventLoop(_cts.Token), _cts.Token);
await task;
}
我已经注释掉了,但是表单仍然冻结。你能在while循环中发布代码吗?它非常长。。。我不想得到反对票,因为我已经处于被禁止的边缘。但是我会冒险的……好吧,不管怎样,我已经试着用你发布的代码来重现这个问题,但是我不能,一切正常。在接收到取消信号时执行的任务中是否有代码?我添加了fullEventloop()
函数。。看看你是否能发现问题。这显然非常不整洁,但我没有看到任何会导致僵局的东西。确定您没有在CancellationToken
上注册取消回调或调用\u任务。等待/\u任务。结果
在任何地方?没有,除了启用和禁用“开始”和“停止”按钮编码中的复选框之外,我没有执行任何其他操作。。我可以给你看,但是每个人都会否决我的问题..屏幕截图中的表单显然是禁用的,但是我没有看到表单的Enabled
属性在代码中的任何地方被设置,所以我倾向于认为问题发生在未发布的代码部分。你的代码示例确实应该,尽量少,但也应该是完整的。例如,您可以开始删除代码位,直到剩下最小值来演示问题为止。到那时,您可能已经自己找到了解决方案。从Invoke
调用中移动数据库访问代码。