-2

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

    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,但是当我尝试用一​​个方法调用来做同样的事情时,它只执行一次。

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

2 回答 2

1

我制作了一个小控制台测试应用程序来测试它,所以我不得不更改方法签名(静态)并且不能ButtonClick在控制台上使用。我通过在程序化的“按钮点击”之间设置睡眠来模拟按钮点击。

这可能会让你开始。

    private static bool isRunning = false;
    private static int clickCounter = 0;
    private static int iterationsCounter = 0;

    static void Main(string[] args)
    {
        Console.WriteLine(“Start”);
        for(int i = 0; i < 7; i++)
        {
            BtnTrade1_Buy_Click();
            System.Threading.Thread.Sleep(1000);
        }
        Console.WriteLine(“END”);
    }


    private static async Task BtnTrade1_Buy_Click()
    {
        iterationsCounter = 0;
        isRunning = !isRunning;
        Console.WriteLine($"Ha: {isRunning} {clickCounter++}");
        await RunningNrunnin();
    }



    private static async Task RunningNrunnin()
    {
        await Task.Run(() => Runit());
    }


    private static void Runit()
    {
        while (isRunning)
        {
            GetTradeHistory();
            System.Threading.Thread.Sleep(100);
        }
    }


    private static void GetTradeHistory()
    {
        Console.WriteLine($"Hello Test {iterationsCounter++}");
    }

当然你不需要所有的柜台和Console.WriteLine()东西。他们在那里让您可视化正在发生的事情。

如果您需要更多信息,请告诉我。

于 2020-05-16T05:13:28.583 回答
0

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

private bool _isRunning;

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

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

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

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

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

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

while (_alive) // Instead of while (true)
于 2020-05-16T19:09:37.280 回答