如何在我的代理检查器代码中制作取消按钮来取消或停止任务异步

问题描述 投票:0回答:1

我不知道如何取消这个

namespace WindowsFormsApplication7
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

//////////////////////////////////////////////////////////////////////////////////////////////////
        public async Task testProxy(string ip, int port)
        {
            bool OK = false;
            try
            {
                WebClient wc = new WebClient();
                wc.Proxy = new WebProxy(ip, port);
                await wc.DownloadStringTaskAsync(new Uri("http://google.com/ncr"));
                OK = true;
                addgood();
                richTextBox2.Text += ip + ":" + port + "\n";
            }
            catch { }
        }
//////////////////////////////////////////////////////////////////////////////////////////////////
        private void bunifuFlatButton1_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "TXT Files | *.txt";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string fileName = openFileDialog1.FileName;
                proxy_list.Text = File.ReadAllText(@fileName);
                proxy_list.Refresh();
            }
        }
//////////////////////////////////////////////////////////////////////////////////////////////////
        private void start_Click(object sender, EventArgs e)  //start checker
        {
            if (proxy_list.Lines.Length < 1)
            {
                MessageBox.Show("Proxy list is Vide");
            }
            else
            {
                var asyncTasks = new Task[proxy_list.Lines.Length];
                for (int i = 0; i < proxy_list.Lines.Length; i++)
                {
                    var tab = proxy_list.Lines[i].Split(':');
                    asyncTasks[i] = testProxy(tab[0], int.Parse(tab[1]));
                }
                Task.WaitAll(asyncTasks);
            }
        }
//////////////////////////////////////////////////////////////////////////////////////////////////
     private void cancel_Click(object sender, EventArgs e) //stop checker
     {

         //cancel here

     }

    }
}
c# asp.net async-await task
1个回答
0
投票

鉴于您提供的上下文以及有关 DownloadStringTaskAsync 的官方 Microsoft 文档,您需要使用 CancellationTokenSource,但该函数无法接收第二个参数来用作取消令牌,一个可能的解决方案是开发您的自己的 DownloadString AskAsync() 在这里我向您展示一个适合我的示例:

public static class WebClientExtensions {

    public static Task<string> DownloadStringTaskAsync(this WebClient webClient, string address, CancellationToken cancellationToken) {
        var tcs = new TaskCompletionSource<string>();
        cancellationToken.Register(() => webClient.CancelAsync());

        webClient.DownloadStringCompleted += (sender, e) => {
            if (e.Cancelled) {
                tcs.TrySetCanceled();
            } else if (e.Error != null) {
                tcs.TrySetException(e.Error);
            } else {
                tcs.TrySetResult(e.Result);
            }
        };

        webClient.DownloadStringAsync(new Uri(address));
        return tcs.Task;
    }
}

现在有了您自己开发的DownloadStringTaskAsync,您可以使用令牌,如下所示:

private CancellationTokenSource cancellationTokenSource;

public async Task testProxy(string ip, int port, CancellationToken cancellationToken) {
    try {
        WebClient wc = new WebClient();
        wc.Proxy = new WebProxy(ip, port);
        await wc.DownloadStringTaskAsync("http://google.com/ncr", cancellationToken);
    } catch (OperationCanceledException) {
        // Task cancelled, handle as needed
        MessageBox.Show("WORK!");
    }
}

如果其他人遇到这个问题,这里是对我有用的完整代码:

public partial class Form1 : Form {
    private TextBox proxy_list;
    private Button startButton;
    private Button cancelButton;

    private CancellationTokenSource cancellationTokenSource;

    public Form1() {
        InitializeComponents();
    }

    private void InitializeComponents() {
        this.proxy_list = new TextBox();
        this.startButton = new Button();
        this.cancelButton = new Button();
        proxy_list.Text = "192.168.1.1:8080\n" +
              "192.168.1.2:8080\n" +
              "192.168.1.3:8080";

        // proxy_list
        this.proxy_list.Location = new System.Drawing.Point(12, 12);
        this.proxy_list.Multiline = true;
        this.proxy_list.Size = new System.Drawing.Size(260, 300);
        this.Controls.Add(this.proxy_list);

        // startButton
        this.startButton.Location = new System.Drawing.Point(12, 318);
        this.startButton.Size = new System.Drawing.Size(100, 30);
        this.startButton.Text = "Start";
        this.startButton.Click += new System.EventHandler(this.startButton_Click);
        this.Controls.Add(this.startButton);

        // cancelButton
        this.cancelButton.Location = new System.Drawing.Point(118, 318);
        this.cancelButton.Size = new System.Drawing.Size(100, 30);
        this.cancelButton.Text = "Cancel";
        this.cancelButton.Click += new System.EventHandler(this.cancel_Click);
        this.Controls.Add(this.cancelButton);
    }

    public async Task testProxy(string ip, int port, CancellationToken cancellationToken) {
        try {
            WebClient wc = new WebClient();
            wc.Proxy = new WebProxy(ip, port);
            await wc.DownloadStringTaskAsync("http://google.com/ncr", cancellationToken);
        } catch (OperationCanceledException) {
            // Task cancelled, handle as needed
            MessageBox.Show("WORK!");
        }
    }

    private async void startButton_Click(object sender, EventArgs e) {
        if (proxy_list.Lines.Length < 1) {
            MessageBox.Show("Proxy list is empty");
        } else {
            cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken = cancellationTokenSource.Token;
            foreach (var line in proxy_list.Lines) {
                var tab = line.Split(':');
                if (tab.Length == 2 && int.TryParse(tab[1], out int port)) {
                    await testProxy(tab[0], port, cancellationToken);
                } else {
                    MessageBox.Show("Invalid proxy format: " + line);
                }
            }
        }
    }

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

public static class WebClientExtensions {

    public static Task<string> DownloadStringTaskAsync(this WebClient webClient, string address, CancellationToken cancellationToken) {
        var tcs = new TaskCompletionSource<string>();
        cancellationToken.Register(() => webClient.CancelAsync());

        webClient.DownloadStringCompleted += (sender, e) => {
            if (e.Cancelled) {
                tcs.TrySetCanceled();
            } else if (e.Error != null) {
                tcs.TrySetException(e.Error);
            } else {
                tcs.TrySetResult(e.Result);
            }
        };

        webClient.DownloadStringAsync(new Uri(address));
        return tcs.Task;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.