簡體   English   中英

在多線程應用程序中單擊按鈕沒有影響

[英]No effect on button click in multithreaded application

除停止按鈕外,一切正常。 (按鈕3和按鈕4 OnClick):

我制作了一個具有四個按鈕的應用程序。

它是一個多線程應用程序。

按鈕1和2將開始生成線程。

按鈕3和4將分別停止該過程。

但這似乎不起作用。

這是我的代碼:

public partial class Form1: Form
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    CancellationToken token;

    public Form1()
    {
        InitializeComponent();
        token = cancellationTokenSource.Token;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Task t = Task.Run(() =>
        {
            while (true)
            {
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    Action act = () => textBox1.Text = Convert.ToString(i);
                    textBox1.Invoke(act);
                }
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                } 
            }
        }, token);
        }

    private void button2_Click(object sender, EventArgs e)
    {
        //token.Cancel();
    }

    private void button3_Click(object sender, EventArgs e)
    {
        Task t1 = Task.Run(() =>
        {
            while (true)
            {
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    Action act = () => textBox2.Text = Convert.ToString(i);
                    textBox2.Invoke(act);
                }
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                } 
            }
        }, token);
    }

    private void button4_Click(object sender, EventArgs e)
    {
        //token.Cancel();
    }
}

更新

這是更新的代碼:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MultiThreading_Start_Stop_Counter
{
public partial class Form1 : Form
{
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    CancellationToken token;
    CancellationTokenSource cancellationTokenSource1 = new CancellationTokenSource();
    CancellationToken token1;

    public Form1()
    {
        InitializeComponent();
        token = cancellationTokenSource.Token;
        token1 = cancellationTokenSource1.Token;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Task t = Task.Run(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                if (token.IsCancellationRequested)
                {
                    token.ThrowIfCancellationRequested();
                }
                // your code
                System.Threading.Thread.Sleep(1000);
                Action act = () => textBox1.Text = Convert.ToString(i);
                textBox1.Invoke(act);
            }
        });
        }

    private void button2_Click(object sender, EventArgs e)
    {
        cancellationTokenSource.Cancel();
    }

    private void button3_Click(object sender, EventArgs e)
    {
        Task t1 = Task.Run(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                if (token1.IsCancellationRequested)
                {
                    token1.ThrowIfCancellationRequested();
                }
                // your code
                System.Threading.Thread.Sleep(1000);
                Action act = () => textBox2.Text = Convert.ToString(i);
                textBox2.Invoke(act);
            }
        });
    }

    private void button4_Click(object sender, EventArgs e)
    {
        cancellationTokenSource1.Cancel();
    }
}
}

現在,任務正在取消,但有以下例外:

mscorlib.dll中發生類型'System.OperationCanceledException'的異常,但未在用戶代碼中處理。其他信息:操作已取消。

解決了:

用於while循環。 謝謝!

  • Cancel方法屬於CancellationTokenSource,因此無法在CancellationToken上調用它
  • 如果(token.IsCancellationRequested)僅在100秒后才被調用,所以也許您只是沒有等待足夠長的時間或更可能將支票放在錯誤的位置

就像@Roman所說的那樣,

如果在不同的任務中請求令牌,則應該為每個CancellationToken創建一個新的CancellationTokenSource

CancellationTokenSource cancellationTokenSource1, cancellationTokenSource2;
CancellationToken token1, token2;

制作兩個不同的CancellationTokenSourceCancellationToken

根據您的取消情況,在如下所示的for循環或while循環中使用它們。

for (int i = 0; i < 100; i++)
{
    if (token1.IsCancellationRequested)
    {
        token1.ThrowIfCancellationRequested();
    }
    // your code
    System.Threading.Thread.Sleep(1000);
    Action act = () => textBox1.Text = Convert.ToString(i);
    textBox1.Invoke(act);
}

要么

while (token1.IsCancellationRequested)
{
}

檢查令牌是否已取消的部分應放在for循環內。

for (int i = 0; i < 100; i++)
{
     if (token.IsCancellationRequested)
     {
         token.ThrowIfCancellationRequested();
     }
     System.Threading.Thread.Sleep(1000);
     Action act = () => textBox1.Text = Convert.ToString(i);
     textBox1.Invoke(act);
}

另外,您拋出OperationCanceledException並沒有捕獲它。

如果您不想處理該異常,則可以為while循環引入一些變量,例如:

Task t = Task.Run(() =>
        {
            var run = true;
            while (run)
            {
                for (int i = 0; i < 100; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        run = false;
                        break;
                    }
                   //loop code
                } 
            }
        }, token);

button2應該包含用於取消令牌的代碼cancelTokenSource.Cancel ();。

並且您需要按鈕3和4的不同的CancellationTokenSource和CancellationToken。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM