如何从C# Task中返回int值?WinForms异步开发技术求助
如何从异步Task中返回int值并更新WinForms GUI
我已通过异步编程实现了不阻塞WinForms GUI的函数,现在需要解决的问题是:如何从Task中返回int值,并用这些值更新GUI对应的变量(比如currentMana和currentReadiness)。相关代码如下:
MainUI.cs
private void button_StartStop_Click(object sender, EventArgs e) { if (!Profile.ProfileLoaded) { return; } if (!UABA.Status) { button_StartStop.BackgroundImage = ((Image)(Properties.Resources.Stop_Button)); UABA.Status = true; Task.Run(() => Main.RunAsync(this)); } else { button_StartStop.BackgroundImage = ((Image)(Properties.Resources.Play_Button)); UABA.Status = false; } }
Main.cs
public static async Task RunAsync(MainUI form_mainUI) { while (true) { if (UABA.Status) { await Task.Run(() => GameData.GetCharacterWindowInformationAsync()); UI.GameData.Character.UpdateCurrentManaValue(); UI.GameData.Character.UpdateCurrentReadiness(); } } }
GameData.cs
public static async Task GetCharacterWindowInformationAsync() { List<Task<int>> tasks = new List<Task<int>>(); if (MonitorMana.MonitoringManaBar) { var gameData = new GameData(); tasks.Add(Task.Run(() => gameData.ReadPixelsInALineAsync())); } if (MonitorReadiness.MonitoringReadinessBar) { var gameData = new GameData(); tasks.Add(Task.Run(() => gameData.GetCurrentReadiness())); } await Task.WhenAll(tasks); //等待完成后,我希望使用每个Task返回的int值更新GUI所用的不同变量(如currentMana和currentReadiness)。 } public Task<int> ReadPixelsInALineAsync() { //Do Work Here return Task.FromResult(resultOfSomeWork); }
解决方案
要获取Task返回的int值并更新对应变量,你可以通过以下方式实现:
单独跟踪每个任务,明确结果对应关系
不要把所有任务都放进同一个List<Task<int>>,而是分别声明变量存储每个任务,这样就能直接区分哪个结果对应mana,哪个对应readiness:// 修改GameData.cs中的GetCharacterWindowInformationAsync方法 public static async Task GetCharacterWindowInformationAsync(MainUI form) { Task<int> manaTask = null; Task<int> readinessTask = null; if (MonitorMana.MonitoringManaBar) { var gameData = new GameData(); manaTask = Task.Run(() => gameData.ReadPixelsInALineAsync()); } if (MonitorReadiness.MonitoringReadinessBar) { var gameData = new GameData(); readinessTask = Task.Run(() => gameData.GetCurrentReadiness()); } // 等待所有任务完成 await Task.WhenAll(manaTask, readinessTask); // 处理返回值并更新UI(注意:WinForms控件必须在UI线程更新) if (manaTask != null) { int currentMana = manaTask.Result; // 任务已完成,直接取Result安全 // 通过UI实例调用线程安全的更新方法 form.UpdateMana(currentMana); } if (readinessTask != null) { int currentReadiness = readinessTask.Result; form.UpdateReadiness(currentReadiness); } }添加UI线程安全的更新方法
在MainUI.cs中添加线程安全的UI更新方法,确保控件操作在UI线程执行:public void UpdateMana(int value) { if (InvokeRequired) { Invoke(new Action<int>(UpdateMana), value); return; } // 这里替换成你的实际UI控件更新逻辑 // 例如:label_Mana.Text = $"当前 mana: {value}"; UI.GameData.Character.CurrentMana = value; UI.GameData.Character.UpdateCurrentManaValue(); } public void UpdateReadiness(int value) { if (InvokeRequired) { Invoke(new Action<int>(UpdateReadiness), value); return; } // 替换成实际UI更新逻辑 UI.GameData.Character.CurrentReadiness = value; UI.GameData.Character.UpdateCurrentReadiness(); }优化异步调用,避免不必要的线程切换
原Main.cs中await Task.Run(() => GameData.GetCharacterWindowInformationAsync());可以简化,因为GetCharacterWindowInformationAsync本身就是异步方法,不需要再包一层Task.Run,直接调用即可:// 修改Main.cs中的RunAsync方法 public static async Task RunAsync(MainUI form_mainUI) { while (true) { if (UABA.Status) { await GameData.GetCharacterWindowInformationAsync(form_mainUI); } // 可以添加短暂延迟,避免循环占用过多CPU await Task.Delay(100); } }
内容的提问来源于stack exchange,提问作者bjcasey
相关产品推荐
相关产品推荐

