Как прервать конкретный поток в параллельной библиотеке задач с C # - PullRequest
0 голосов
/ 25 сентября 2011

У меня есть эта непростая задача, которую я некоторое время пытался выполнить, но до сих пор не мог придумать, как это сделать.в любом случае вот сценарий ...

У меня есть приложение winform, содержащее список и кнопку.просмотр списка содержит 1 столбец, в котором хранятся данные, которые мне нужно передать моим функциям позже.столбец содержит, скажем, 50 строк, содержащих список ссылок.

Теперь у меня есть эта функция, которую я использую для извлечения и получения содержимого этих ссылок (5 ссылок за раз) в параллельном многопоточном режиме, используя(Task Parallel Library):

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

Теперь приведенный выше код работает отлично ... но иногда я хочу, чтобы пользователь прервал определенный поток, который в данный момент запущен, и продолжил работу с остальными потоками в списке... это достижимо в этом?если так, пожалуйста, помогите мне .. Я был бы очень признателен за любое решение или предложения ..

Ответы [ 2 ]

2 голосов
/ 28 сентября 2011

Попробуйте использовать библиотеку задач с токенами отмены. Я считаю, что это более элегантный и безопасный подход, чтобы делать свое дело. Вот хороший пример того, как это сделать:

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

0 голосов
/ 27 сентября 2011

хорошо, после борьбы с этим я наконец нашел эффективное и простое решение для этого ..

мне потребовалась только хеш-таблица, которая содержит признаки выбранных элементов в списке и простое значение bool.индекс - это ключ, а bool (true, false) - это значение.значение bool похоже на (вкл / выкл) переключатель, указывающий, что текущий цикл отменен или нет .. поэтому, чтобы просто прервать конкретный поток, мне нужно передать ключ (индекс) выбранного элемента в моем списке просмотраЦикл foreach и проверьте, включен ли переключатель bool, и это в основном все ...

, поэтому мой окончательный код будет таким:

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

    private Hashtable abortingItem;

Теперь, когда я нажимаю кнопку захвата, этодолжен заполнить хеш-таблицу выбранными признаками ...

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)
//..........................

Теперь, если мне нужно отменить определенный элемент, все, что мне нужно, это выбрать элемент в списке и нажать кнопку отмены

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 все, что мне нужно, это простой оператор if, чтобы проверить, включен или выключен bool:

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

Это просто все.

...