多线程和表单调用不同步

时间:2014-01-08 16:17:43

标签: c# multithreading invoke

我正在使用C#进行多线程和表单方法调用功能的Windows应用程序。这是屏幕和代码

enter image description here

如您所见,我的表单有两个按钮和一个列表视图。单击每个按钮,一组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方法然后启动一个新线程。

1 个答案:

答案 0 :(得分:3)

你做不到。当您中止另一个线程时,线程已经向消息队列发送了一条消息,指出应该添加一个项目。之后线程会发生什么不会阻止消息。

一般情况下使用Thread.Abort也是一个非常糟糕的主意。在任何时间点抛出异常的想法是真的难以使用。在这种情况下,如此多的代码块确实难以推理。我强烈建议您使用类似CancellationToken的内容来执行取消。这可以确保取消只能在您知道安全停止执行的某些时间点发生。