2011-09-25 50 views
-1

我有這個棘手的任務,我一直試圖實現安靜的某個時候,但直到現在我想不出任何使它工作。無論如何這裏是場景...如何用C中止任務並行庫中的特定線程

我有一個winform應用程序包含一個listview和一個按鈕。 列表視圖包含1列,其中包含我稍後需要傳遞給我的函數的數據。該列包含說50行包含鏈接列表。

現在我有這個功能,我使用來獲取和抓住這些鏈接的使用並行多線程模式(任務並行庫)中的內容(一次5個環節),其中:

//List<int> currentWorkingItem //contains the indices of the items in listview 
//List<string> URLsList //contains the URLs of the items in listview 

Parallel.ForEach(URLsList, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, (url, i, j) => 
{ 
    //show to user this link is currently being downloaded by highlighting the item to green... 
    this.BeginInvoke((Action)(delegate() 
    { 
     //current working item 
     mylistview.Items[currentWorkingItem[(int)j]].BackColor = green; 

    })); 

    //here I download the contents of every link in the list... 
    string HtmlResponse = GetPageResponse(url); 

    //do further processing.... 
}); 

現在上面的代碼完美地工作......但有時我希望用戶放棄某個當前正在運行的線程,並繼續處理列表中的其餘線程......是否可以在此實現?如果是的話,請幫我..我真的很感激任何解決方案或建議..

+0

[檢查了這一點(http://msdn.microsoft.com/en-us/library/ dd460721.aspx)。如果這不起作用,您可能需要創建多個任務(一個foreach下載),每個任務可以單獨關閉,而不是Parallel.ForEach。不應該困難。 –

+0

我用簡單的哈希表找到了更好的解決方案... – SolidSnake

+0

使用'字典'而不是散列表。 –

回答

-1

確定與此掙扎後,我終於找到了一個有效的和這一個簡單的解決方案..

它只是要求我散列表,其中包含listview中所選項目的標記和一個簡單的布爾值。索引是關鍵,bool(true,false)是值。布爾值就像一個(開/關)開關指示當前循環被中止或沒有..所以爲了中止特定的線程簡單我需要將我的列表視圖上選定的項目的關鍵(索引)傳遞給foreach循環,並檢查布爾開關打開或關閉,並且基本上它...

所以我的最終代碼會是這樣:

//I declared the hashtable outside the function so I can manage it from different source. 

    private Hashtable abortingItem; 

現在,當我點擊搶按鈕,它應該充滿哈希表與所選indicies ...

abortingItem = new Hashtable(); 

for (int i = 0; i < myURLslist.SelectedItems.Count(); i++) 
{ 
    //false means don't abort this.. let it run 
    abortingItem.Add(myURLslist.SelectedItems[i].index, false); 
} 

//here should be the code of my thread to run the process of grabbing the URLs (the foreach loop) 
//.......................... 
現在

,如果我需要中止specifi C項目所有我需要的是在ListView選擇項並單擊中止按鈕

private void abort_Click(object sender, EventArgs e) 
{ 
    if (abortingItem != null) 
    { 
     for (int u = 0; u < myURLslist.SelectedIndices.Count; u++) 
     { 
      //true means abort this item 
      abortingItem[myURLslist.SelectedIndices[u]] = true; 
     } 
    } 
} 

在我的foreach循環,我需要的是一個簡單的,如果檢查else語句如果布爾是開啓還是關閉:

//List<int> currentWorkingItem //contains the indices of the items in listview 
//List<string> URLsList //contains the URLs of the items in listview 

Parallel.ForEach(URLsList, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, (url, i, j) => 
{ 

//aborting 
if (!(bool)abortingItem[currentWorkingItem[(int)j]]) 
{ 
    //show to user this link is currently being downloaded by highlighting the item to green... 
    this.BeginInvoke((Action)(delegate() 
    { 
     //current working item 
     mylistview.Items[currentWorkingItem[(int)j]].BackColor = green; 

    })); 

    //here I download the contents of every link in the list... 
    string HtmlResponse = GetPageResponse(url); 

    //do further processing.... 
} 
else 
{ 
    //aborted 
} 
}); 

這就是它。

+2

散列表不是線程安全的。不要忘記把鎖放在您的通道上。 –

+0

你是什麼意思? – SolidSnake

2

嘗試使用帶取消標記的任務庫。我發現它更優雅和更安全的方式來做你的事情。這裏是幹什麼的報價很好的例子:

using System; 
using System.Threading.Tasks; 
using System.Threading; 

namespace CancelTask 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Press 1 to cancel task"); 
      var cTokenSource = new CancellationTokenSource(); 
      // Create a cancellation token from CancellationTokenSource 
      var cToken = cTokenSource.Token; 
      // Create a task and pass the cancellation token 
      var t1 = Task<int>.Factory.StartNew(() 
       => GenerateNumbers(cToken), cToken); 

      // to register a delegate for a callback when a 
      // cancellation request is made 
      cToken.Register(() => cancelNotification()); 

      // If user presses 1, request cancellation. 
      if (Console.ReadKey().KeyChar == '1') 
      { 
       // cancelling task 
       cTokenSource.Cancel(); 
      } 
      Console.ReadLine(); 
     } 

     static int GenerateNumbers(CancellationToken ct) 
     { 
      int i; 
      for (i = 0; i < 10; i++) 
      { 
       Console.WriteLine("Method1 - Number: {0}", i); 
       Thread.Sleep(1000); 
       // poll the IsCancellationRequested property 
       // to check if cancellation was requested 
       if (ct.IsCancellationRequested) 
       { 
        break; 
       } 

      } 
      return i; 
     } 

     // Notify when task is cancelled 
     static void cancelNotification() 
     { 
      Console.WriteLine("Cancellation request made!!"); 
     } 
    } 
} 

原創文章可以在這裏找到:http://www.dotnetcurry.com/ShowArticle.aspx?ID=493

相關問題