C#中Dropbox API的DownloadAsync在async Task<bool>中卡死原因咨询
问题根因
- 这是典型的C# UI线程异步死锁问题,触发点是你在按钮点击事件中调用
SetStringAndReturnBoolean(GuiTextBox.Text).Result,用同步方式等待异步任务返回。 - 原本async void版本能正常运行的原因:async void方法内部的await不会被上层同步阻塞,await执行完成后可以正常回到UI线程处理后续逻辑,没有形成循环等待。
- 改async Task
后卡死的逻辑: - 调用
.Result会立即阻塞当前UI线程,等待Task执行完成才会释放线程 SetStringAndReturnBoolean内部的await默认会捕获UI同步上下文,await的异步操作完成后,需要回到UI线程执行后续的返回逻辑- 此时UI线程正被
.Result阻塞等待Task完成,Task又在等待UI线程释放以继续执行,形成死锁,程序永久卡住。
- 调用
修复方案
只需要修改按钮点击事件的调用方式,用await异步等待任务结果,不要用.Result/.Wait()这类同步阻塞方法即可:
private async void Button_Click(object sender, RoutedEventArgs e) { if (!await SetStringAndReturnBoolean(GuiTextBox.Text)) ErrorRun.Text = "Invalid Key"; else { DialogResult = true; Close(); } }
可选优化
如果SetStringAndReturnBoolean方法内部的后续逻辑不需要回到UI线程执行,可以给所有await加上.ConfigureAwait(false),既可以提升性能,也能从方法层面避免这类上下文死锁问题:
private async Task<bool> SetStringAndReturnBoolean(string text) { var keysToCheck = ""; using (var dbx = new DropboxClient("TOKEN")) { using (var response = await dbx.Files.DownloadAsync("/FileToDownload.txt").ConfigureAwait(false)) { keysToCheck = await response.GetContentAsStringAsync().ConfigureAwait(false); } } var keys = keysToCheck.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList(); foreach (var key in keys) if (key == text) return true; return false; }
内容的提问来源于stack exchange,提问作者Armyc84
相关产品推荐
相关产品推荐

