C# WPF 程序按钮单击运行任务直到另一个按钮单击停止或直到取消令牌有效 [英] C# WPF program button click run a task until another button click stop or until cancel token valid

查看:111
本文介绍了C# WPF 程序按钮单击运行任务直到另一个按钮单击停止或直到取消令牌有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个 WPF 应用程序,我想在其中创建一个全局 bool 我假设,在第一个按钮单击时,我将这个 bool 设置为 true 并且我希望它运行一个任务(连续调用一个 API 方法),直到我再次单击该按钮并停止它.这样做的最佳方法是什么?

I am creating a WPF app where I want to have a global bool im assuming, on the first button click I’ll set this bool to true and I want it to run a task (continuously call an API method) until I click the button again and it stops it. What would be the best way to do this?

    private bool running = false;

    private async void BtnTrade1_Buy_Click(object sender, RoutedEventArgs e)
    {
        if (!running)
        {
            running = true;
        }
        else
            running = false;

        if (running)
        {
            RunningNrunnin(running);
            //tradeClient.GetTradeHistory();
        }
    }

    public void RunningNrunnin(bool running)
    {
        if (running)
        {
            Task task = new Task(() =>
            {
                while (running)
                {
                    GetTradeHistory();
                    Thread.Sleep(2000);
                }
            });
            task.Start();
        }
    }

在下面添加

我想一遍又一遍地调用一个方法,直到用户在后台的线程上创建取消请求.我目前拥有它,因此我可以每秒调用一个操作(计数器)并更新 GUI,但是当我尝试使用方法调用执行相同的操作时,它只执行一次.

I would like to call a method over and over until the user creates a cancel request on a thread in the background. I currently had it so I can call a action (a counter) and update the GUI each second but when I try to do this same thing with a method call it executes only once.

// Here is the method I want to call continously until canceled
private async void HistoryTest()
        {
            cancellationToken = new CancellationTokenSource();

            task = Task.Factory.StartNew(async () =>
            {
                while (true)
                {
                    cancellationToken.Token.ThrowIfCancellationRequested();

                    await Client2.GetHistory();
                    await Task.Delay(2000);
                }
            }, cancellationToken.Token);

        }
public async Task GetHistory()
        {
            try
            {
                var response = await Client.Service.GetDataAsync
                    (
                        ProductType.BtcUsd,
                        5,
                        1
                    );
            }
            catch(Exception)
            {
                throw;
            }
        }

推荐答案

除了切换 isRunning 之外,您无需在 BtnTrade1_Buy_Click 事件处理程序中执行任何其他操作字段:

You don't need to do anything else inside the BtnTrade1_Buy_Click event handler, beyond toggling the isRunning field:

private bool _isRunning;

private void BtnTrade1_Buy_Click(object sender, RoutedEventArgs e)
{
    _isRunning = !_isRunning;
}

在循环中获取交易历史的Task 只需启动一次.您可以在 Window_Loaded 事件中启动它.将 Task 存储在私有字段中是一个好主意,以防您决定在某个时候 await 它,但如果您正在处理任务内部的异常,则没有必要.

The Task that is getting the trade history in a loop, needs to be started only once. You could start it in the Window_Loaded event. Storing the Task in a private field is a good idea, in case you decide to await it at some point, but if you are handling the exceptions inside the task it's not necessary.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _ = StartTradeHistoryLoopAsync(); // Fire and forget
}

private async Task StartTradeHistoryLoopAsync()
{
    while (true)
    {
        var delayTask = Task.Delay(2000);
        if (_isRunning)
        {
            try
            {
                await Task.Run(() => GetTradeHistory()); // Run in the ThreadPool
                //GetTradeHistory(); // Alternative: Run in the UI thread
            }
            catch (Exception ex)
            {
                // Handle the exception
            }
        }
        await delayTask;
    }
}

不要忘记在窗口关闭时停止任务.

Don't forget to stop the task when the window is closed.

private void Window_Closed(object sender, EventArgs e)
{
    _isRunning = false;
}

这将停止对 GetTradeHistory() 的调用,但不会停止循环.您可能需要再添加一个私有的 bool 字段来控制循环本身:

This will stop the calls to GetTradeHistory(), but will not stop the loop. You may need to add one more private bool field to control the loop itself:

while (_alive) // Instead of while (true)

这篇关于C# WPF 程序按钮单击运行任务直到另一个按钮单击停止或直到取消令牌有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆