我正在使用C#进行多线程和表单方法调用功能的Windows应用程序。这是屏幕和代码
如您所见,我的表单有两个按钮和一个列表视图。单击每个按钮,一组100个项目将添加到列表视图中。这些是使用单独的线程添加的。这是表单代码
private void btnTest1_Click(object sender, EventArgs e)
{
LogWriter.Log("Test1 click started");
if (this.t != null && this.t.IsAlive)
{
this.t.Abort();
LogWriter.Log("Thread aborted in test1 click");
}
this.testComponent.InitialValue = 1;
this.t = new Thread(this.ts);
LogWriter.Log("New thread started in test1 click");
this.t.Start();
}
private void btnTest2_Click(object sender, EventArgs e)
{
LogWriter.Log("Test2 click started");
if (this.t != null && this.t.IsAlive)
{
LogWriter.Log("Thread aborted in test2 click");
this.t.Abort();
}
this.testComponent.InitialValue = 4000;
this.t = new Thread(this.ts);
LogWriter.Log("New thread started in test2 click");
this.t.Start();
}
internal void AddToList(ListViewItem listItem)
{
this.Invoke((MethodInvoker)delegate
{
this.listView1.Items.Add(listItem);
LogWriter.Log("Added " + listItem.Text);
});
}
private void Form1_Load(object sender, EventArgs e)
{
LogWriter.ClearLog();
this.testComponent = new TestComponent();
this.ts = new ThreadStart(this.testComponent.DoSomething);
this.t = new Thread(ts);
}
这是TestComponent类
internal class TestComponent
{
public int InitialValue { get; set; }
public void DoSomething()
{
for (int i = this.InitialValue; i <= InitialValue + 100; i++)
{
ListViewItem listItem = new ListViewItem();
listItem.Text = i.ToString();
Program.AppForm1.AddToList(listItem);
}
}
}
LogWriter只是将事件记录到文本文件中。 这里的概念是,只要用户点击Test1按钮,就会将一组项目添加到列表中。即使在添加项目时,用户也可以单击Test2按钮,这将停止当前添加的项目,并将开始添加新项目。
当我从一个单独的线程向listview添加项目时,我使用的是Invoke方法。因此,当我依次单击Test1和Test2按钮时,我在日志中得到以下结果。
2014-01-08 21:29:12.764 - Test1 click started
2014-01-08 21:29:12.778 - New thread started in test1 click
2014-01-08 21:29:12.788 - Added 1
2014-01-08 21:29:12.791 - Added 2
2014-01-08 21:29:12.796 - Added 3
2014-01-08 21:29:12.802 - Added 4
2014-01-08 21:29:13.127 - Test2 click started
2014-01-08 21:29:13.129 - Thread aborted in test2 click
2014-01-08 21:29:13.149 - New thread started in test2 click
2014-01-08 21:29:13.154 - Added 5
2014-01-08 21:29:13.157 - Added 4000
2014-01-08 21:29:13.160 - Added 4001
2014-01-08 21:29:13.163 - Added 4002
2014-01-08 21:29:13.166 - Added 4003
从上面的日志中可以看出,不应该记录“Added 5”,因为上面的条目显示“线程已中止并且新线程已启动”。现在我的问题是,
当调用者线程中止时如何停止执行调用OR
如何等到执行invoke方法然后启动一个新线程。
答案 0 :(得分:3)
你做不到。当您中止另一个线程时,线程已经向消息队列发送了一条消息,指出应该添加一个项目。之后线程会发生什么不会阻止消息。
一般情况下使用Thread.Abort
也是一个非常糟糕的主意。在任何时间点抛出异常的想法是真的难以使用。在这种情况下,如此多的代码块确实难以推理。我强烈建议您使用类似CancellationToken
的内容来执行取消。这可以确保取消只能在您知道安全停止执行的某些时间点发生。