我在这段代码中使用Semaphore
static Semaphore s = new Semaphore(1,1);
private void button2_Click(object sender, EventArgs e)
{
Thread[] t = new Thread[full_list];
for(int i=0;i<full_list;i++)
{
if (sorted_list[i].audio_node != null)
if (sorted_list[i].audio_node.Checked == true)
{
t[i] = new Thread(DownloadFile);
t[i].Start(sorted_list[i]);
}
}
}
private void DownloadFile(object a)
{
s.WaitOne();
if (InvokeRequired)
{
BeginInvoke(new DownloadFileDelegate(DownloadFile),new object[1] {a} );
return;
}
else
{
download process....
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
s.Release();
}
但它不起作用,我的prorgram冻结了。我正在尝试解决这个问题,但我不知道它为何与Semaphore不兼容。所有组件都包括正确下载工作。
答案 0 :(得分:1)
你在非gui线程上运行DownloadFile
。在方法中,您获取信号量,然后调用InvokeRequired
。它会返回true
,因为你不在gui线程上,所以你调用DownloadFile on the gui thread. You then return without releasing the semaphore, so when
下载文件`在gui线程上运行它会尝试做的第一件事是获取信号量,因为它不会阻止它。
在你的代码中创建一个线程并没有多大意义,只是要在gui线程上安排一个回调。你真正需要做的是在非gui线程上下载文件,然后当你得到它时,回调到gui线程来处理你下载的内容。
关于信号量,您应该将代码包装在try\finally
块中以确保它始终被释放,即使您在代码中间有一个返回值:
s.WaitOne();
try
{
// Rest of method
}
finally
{
s.Release();
}