Reputation: 1181
I'm working on a windows application using C# with multithreading and form method invoking features. Here are the screens and code
As you can see, my form has two buttons and a listview. On click of each button, a set of 100 items are added to the listview. These are added using a separate thread. Here is the form code
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);
}
Here is the TestComponent class
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);
}
}
}
And the LogWriter just logs the events to a text file. Here the concept is, as soon as user clicks on Test1 button, set of items are added to list. Even while the items are being added, user can click on Test2 button, which will stop current addition of items and will start addition of new set of items.
As im adding items to listview from a separate thread, I am using Invoke method. So when I click Test1 and Test2 buttons one after the other, I'm getting the following result in the log.
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
As you can see from the above log, "Added 5" should not be logged because the entry above it says "thread is aborted and a new thread is started". Now my question is,
how do I stop the execution of the invoke when the caller thread is aborted OR
how to wait until the invoke method is executed and then start a new thread.
Upvotes: 1
Views: 149
Reputation: 203825
You can't. When you're aborting the other thread that thread has already sent a message to the message queue stating that an item should be added. What happens to the thread after that won't stop the message.
It's also a very bad idea to use Thread.Abort
in general. The idea of having an exception thrown at any point in time is really hard to work with. So many code blocks get really hard to reason about in such situations. I would strongly recommend that you use something like a CancellationToken
instead to perform the cancellation. This ensures that the cancellation can only happen at certain points in time at which you know that it's safe to stop executing.
Upvotes: 3