2014-01-21 30 views
2

我用旗语在这段代码信号灯控制downloadinf过程

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冻结。我试图解决这个问题,但我不知道为什么它不适用于信号量。所有组件都包括正确下载工作。

回答

1

您在非gui线程上运行DownloadFile。在获取信号量的方法中,然后致电InvokeRequired。它将返回true,因为你不在gui线程中,所以你调用DownloadFile on the gui thread. You then return without releasing the semaphore, so when DownloadFile`在gui线程上运行,它将尝试做的第一件事就是获取信号量,并且因为它不能阻塞它。

在你的代码中创建一个只需要在gui线程上调用回调的线程没有多大意义。你真正需要做的是在non-gui线程上下载文件,然后当你有回调到gui线程来处理你下载的内容。

关于旗语,你应该换行代码在try\finally块,以确保它总是释放,即使你有代码中间的回报:

s.WaitOne(); 
try 
{ 
    // Rest of method 
} 
finally 
{ 
    s.Release(); 
} 
+0

关于下载,我当我下载时,希望在Gui中显示进度。 – jenius

+0

@jenius - 当你在一个线程上下载的时候,你可以在gui线程上调用一个'BeginInvoke'方法来说出已经下载了多少,相应的更新gui。 – Sean

+0

我这样做,现在信号量不会冻结我的程序,但它仍允许同时下载2个或更多文件。这是我无法接受的。 – jenius