【发布时间】:2015-09-25 22:27:36
【问题描述】:
在我的应用程序中,我有一个 Task<bool> 类型的异步 Save() 方法,如果保存成功,它将通过 bool 发出信号。各种事情都可能发生在 Save() 中,它通过处理异常的另一层调用,显示可能的对话框等,但这没关系,我只关心布尔结果。
现在我必须在一个非异步方法中调用这个方法(这是一个使用过的框架的覆盖,所以我不能让它异步)
代码看起来有点像:
public override void SynchronousMethodFromFramework()
{
bool result = false;
Task.Run(async () => result = await Save());
return result;
}
问题是,在保存完成之前返回结果(因此总是错误的)。 它怎么能解决这个问题?我已经尝试过 Task.WaitAll()、.Result、.ConfigureAwaiter(false),但我所做的一切似乎都完全冻结了我的应用程序。
更多信息:
使用的 WPF 框架是 Caliburn.Micro。我的 MainviewModel 是 Conductor<IScreen>.Collection.OneActive,它在 Tabcontrol 中执行多个视图模型。每个 ViewModel 都是某种编辑屏幕。
当最终用户关闭应用程序(通过右上角的红色 X )时,我想遍历所有选项卡以查看它们是否有待处理的更改。
mainviewmodel的代码:
public override void CanClose(Action<bool> callback)
{
//for each tab, go to it and try to close it.
//If pending changes and close is not succeeded (eg, user cancels), abort aplication close
bool canclose = false;
Action<bool> result = b => canclose = b;
for (int i = Items.Count - 1; i >= 0; i--)
{
var screen = Items[i];
screen.CanClose(result);
if (!canclose)
{
callback(false);
return;
}
}
callback(true);
}
我的“编辑”-ViewModels 中的代码:
private async Task<bool> SavePendingChanges()
{
if (!Entity.HasDirtyContents())
return true;
bool? dialogResult = DialogProvider.ShowMessageBox("Save changes",
"There are pending changes, do you want to save them ?", MsgBoxButton.YesNoCancel);
if (dialogResult == null)
return false;//user cancelled
if (dialogResult == false)
return true;//user doesn't want to save, but continue
//try to save; if save failed => return false
return await (Save());
}
public override void CanClose(Action<bool> callback)
{
var task = SavePendingChanges();
task.Wait();
bool result = task.Result;
callback(result);
}
“CanClose”是 CM 提供的非异步框架方法 ...
【问题讨论】:
-
谷歌是你的朋友:msdn.microsoft.com/en-us/library/dd235635(v=vs.110).aspx。只需从您的任务中创建一个变量并为它创建一个
.Wait()。 -
如果你在 UI 线程上阻塞了一个方法,那么 UI 就会冻结。这是非常基本的,你无能为力。
-
如前所述,我已经尝试过了,我完全挂起应用程序。我怀疑这是因为在 Save() 方法链的某个地方,设置了一个变量“IsBusy”,它数据绑定到 WPF UI 控件的可见性,一个“BizzySpinner”表示正在发生的事情。
-
好的,我应该马上说:您需要提供更多详细信息。如果要解冻 UI,则不能阻止该线程。为了推荐一些东西,你需要提供更多的背景信息。
-
你为什么不这样做: public override async void SynchronousMethodFromFramework() ?我不记得异步应该在覆盖之前还是之后。即使它是被覆盖的方法,您也应该能够做到。检查这个。
标签: c# asynchronous caliburn.micro