C#主线程被第二个线程使用信令阻塞?

时间:2011-07-15 15:45:21

标签: c# winforms threadpool autoresetevent

GetFiles创建第二个调用CopyFiles的线程,我只是在每次复制文件时尝试用文件名填充列表框,但是一旦代码命中行:

listBox1.Invoke((MethodInvoker)delegate { PrintProgress(i.ToString()); }, new object[] { }); 

主线程被阻止,有什么想法吗?

void GetFiles()
{
    AutoResetEvent autoEvent = new AutoResetEvent(false);
    ThreadPool.QueueUserWorkItem(new WaitCallback(CopyFiles),autoEvent);

    //some unrelated code

    autoEvent.WaitOne();
}

private void CopyFiles(object stateInfo)
{
    for (int i = 0; i < 10; i++)
    {
        //SetControlPropertyValue(listBox1, i.ToString());       
        listBox1.Invoke((MethodInvoker)delegate { PrintProgress(i.ToString()); }, new object[] { });
        Thread.Sleep(1000);
    }

    // Signal that this thread is finished.
    ((AutoResetEvent)stateInfo).Set();     
}

private void PrintProgress(string number)
{
    listBox1.Items.Add(number);
}

2 个答案:

答案 0 :(得分:3)

你的主要线程因为你正在调用GetFiles()而被绞死。所以你有一个死锁,这是一个场景:

主线程将在第autoEvent.WaitOne();行阻塞,等待信号继续,但它永远不会收到该信号,因为该信号取决于在主线程“listBox1.Items.Add(number);”上执行代码并且最后一个将阻止等待autoEvent.WaitOne()完成。死锁。

要修复它从另一个线程而不是主线程运行GetFiles()方法,所以:

ThreadPool.QueueUserWorkItem(new WaitCallback((_) => { GetFiles(); }), null);

答案 1 :(得分:1)

可能你正在与主线程上的事件同步,它只是无法处理调用。

您应该稍后在GetFiles方法中发布使用该事件的代码。