C# WPF 程序按钮单击运行任务直到另一个按钮单击停止或直到取消令牌有效 [英] C# WPF program button click run a task until another button click stop or until cancel token valid
问题描述
我正在创建一个 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屋!