C#操纵UI线程中的线程

时间:2013-11-22 13:02:44

标签: c# multithreading abort

我有相当多的编程知识,但这是我第一次在C#上使用多线程应用程序,所以我正在寻求有关我的问题的帮助。

首先是代码,

public frmCEX()
    {
        InitializeComponent();
        refreshTicker();
    }

    private void btnRefresh_Click(object sender, EventArgs e)
    {
        refreshTicker();
    }

    private void refreshTicker()
    {
        ssStatus.Text = "Updating ticker..";
        btnRefresh.Text = "Updating";
        btnRefresh.Enabled = false;
        ssUpdated.Text = "Last updated: -";

        APIManager apim = new APIManager();
        Ticker tk = apim.getTicker();

        //blablabla, do some work

        ssUpdated.Text = "Last updated: " + DateTime.Now.ToString();
        ssStatus.Text = "";
        btnRefresh.Text = "Refresh";
        btnRefresh.Enabled = true;
    }

    private void cbxRefresh_CheckedChanged(object sender, EventArgs e)
    {
        if (cbxRefresh.Checked)
        {
            Thread thread1 = new Thread(() => BGRefreshThread(Convert.ToInt32(nupRefreshSecs.Value)));
            thread1.Start();
        }
        else
        {
          // IF REFRESH CHECKBOX IS UNCHECKED, STOP THE THREAD THAT IS REFRESHING
        }
    }

    private void BGRefreshThread(int delay)
    {
        refreshTicker();
        System.Threading.Thread.Sleep(delay * 1000);
    }

我的主要问题在于cbxRefresh_CheckedChanged方法,基本上,这是如何工作的,当用户检查主UI中的“自动刷新”复选框时,checkedchanged方法将创建一个新线程{{1}在后台运行并刷新自动收报机,一旦再次取消选中该复选框,它将结束刷新自动收报机的线程。

但是,我在线程启动时遇到问题,因为一旦BGRefreshThread方法结束,当下次取消选中该复选框时,该线程就不再存在于上下文中。

有人可以建议我如何让这个工作吗?对于多线程编程来说真的很陌生。

**编辑:我找到了解决这个问题的方法,但是现在,当新创建的线程试图调用“refreshTicker”时,它会更新主UI上的标签和按钮(位于主线程上),它给了我这个错误:

  

跨线程操作无效:从>创建线程以外的线程访问控制'btnRefresh'。

对此有何建议?**

2 个答案:

答案 0 :(得分:1)

首先,线程变量应该是实例成员,因此您可以随时访问它。

我做什么来优雅地停止线程:在创建和启动线程之前,我创建了一个ManualResetEvent,我用它来表示线程退出:

private ManualResetEvent m_stopThread = new ManualResetEvent(false);

要停止线程,我在代码中的某处设置事件并等待线程结束:

m_stopThread.Set();
m_myThread.Join();

线程的代码需要考虑停止:

while (true)
{
    // Stop the thread if the handle is set after 1 ms
    if (m_stopThread.WaitOne(1, false))
        break;

    // Do some work
}

答案 1 :(得分:0)

您需要将线程保存在不超出范围的变量中。

private Thread thread1;

 private void cbxRefresh_CheckedChanged(object sender, EventArgs e)
    {
        if (cbxRefresh.Checked)
        {
            thread1 = new Thread(() => BGRefreshThread(Convert.ToInt32(nupRefreshSecs.Value)));
            thread1.Start();
        }
        else
        {
          thread1.Abort();
        }
    }

请注意,有一些检查缺失,中止不是结束线程的好方法。