2014-01-21 27 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