2

3 つのボタンを持つ Windows フォームがあります。1 つのボタンで BlockingCollection にエントリを追加します。1 つはリストの処理を開始し、もう 1 つはリストの処理を停止します。

BlockingCollection にエントリを追加できます。[開始] をクリックすると、期待どおりにリストが消費されます。私はまだ新しいアイテムを追加することができ、それらは引き続き消費されます. ただし、[停止] ボタンをクリックすると、タスクは停止しますが、[開始] ボタンで再度開始することはできません。

タスクが再び開始されないという、タスクのキャンセルで何が間違っていますか? タスクのキャンセルに関する無数の項目を読みましたが、まだ「理解」していません。

どんな助けでも素晴らしいでしょう。これがコードです...

    // Blocking list for thread safe queuing
    private BlockingCollection<QueueItem> ItemList = new BlockingCollection<QueueItem>();
    private CancellationTokenSource CancelTokenSource = new CancellationTokenSource();
    private int MaxConsumers = 3;

    // Form initialisation
    public MainForm()
    {
        InitializeComponent();
    }

    // Create an async consumer and add to managed list
    private void CreateConsumer(int iIdentifier)
    {
        Task consumer = Task.Factory.StartNew(() =>
        {
            foreach (QueueItem item in ItemList.GetConsumingEnumerable())
            {
                Console.WriteLine("Consumer " + iIdentifier.ToString() + ": PROCESSED " + item.DataName);
                Thread.Sleep(894);

                if (CancelTokenSource.IsCancellationRequested)
                    break; // Cancel request
            }
        }, CancelTokenSource.Token);
    }

    // Add a new item to the queue
    private void buttonAdd_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            Task.Factory.StartNew(() =>
            {
                // Add an item
                QueueItem newItem = new QueueItem(RandomString(12));

                // Add to blocking queue
                ItemList.Add(newItem);
            });
        }
    }

    // Start button clicked
    private void buttonStart_Click(object sender, EventArgs e)
    {
        buttonStart.Enabled = false;
        buttonStop.Enabled = true;

        // Create consumers
        for (int i = 0; i < MaxConsumers; i++)
        {
            CreateConsumer(i);
        }
    }

    // Stop button clicked
    private void buttonStop_Click(object sender, EventArgs e)
    {
        CancelTokenSource.Cancel();

        buttonStop.Enabled = false;
        buttonStart.Enabled = true;
    }

    // Generate random number
    private static Random random = new Random((int)DateTime.Now.Ticks);
    private string RandomString(int size)
    {
        StringBuilder builder = new StringBuilder();
        char ch;
        for (int i = 0; i < size; i++)
        {
            ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
            builder.Append(ch);
        }

        return builder.ToString();
    }
4

1 に答える 1

5

キャンセルするように構成されている同じキャンセル トークンを再利用します。

そのため、新しいタスクを開始するときに新しいトークンを作成します。

于 2012-08-02T09:22:44.577 に答える