c#主线程被使用信号的第二个线程阻塞

本文关键字:线程 第二个 信号 | 更新日期: 2023-09-27 18:02:07

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);
}

c#主线程被使用信号的第二个线程阻塞

你的主线程挂起,因为你正在从它调用GetFiles()。所以你有一个死锁,这是一个场景:

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

要解决这个问题,在另一个线程而不是主线程中运行GetFiles()方法,因此:

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

可能您正在与主线程上的事件同步,而主线程无法处理调用。

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