使用库Сatel最新版本(3.8.1 beta)。
如何在对话框窗口中使用TAP方法?
实施例。 在主ViewModel中调用方法
private bool ShowDialogWindow()
{
var typeFactory = TypeFactory.Default ;
var vm = typeFactory.CreateInstanceWithParametersAndAutoCompletion<LoginWindowViewModel>();
return _uiVisualizerService.ShowDialog(vm) ?? false;
}
在LoginWindowViewModel中我有Command(也尝试AsynchronousCommand),这叫做方法
public async Task<int> Test(string login, string password)
{
var a = await Task<int>.Factory.StartNew(() =>
{
using (var uow = new UnitOfWork<TSDbContext>())
{
var userRep = uow.GetRepository<IUserRepository>();
userRep.GetAll();
return 5;
}
});
a++;
return a;
}
只有在关闭对话框窗口时才从等待方法获得结果。 锁出现在行
var uow = new UnitOfWork()
ConfigureAwait(false) - 无助于解决问题
当我删除UnitOfWork时 - 方法有效
当我将方法代码更改为此时 var d = TypeFactory.Default.CreateInstanceWithParameters(); 返回5;
阻止也会在TypeFactory ......
行上重现根据服务,对话框中不允许使用Catel
答案 0 :(得分:3)
注意:我编辑了这个答案,因此它包含了这个问题的答案。上一个答案包含一些关于主题入门者调查问题的提示。
您在MainViewModel的构造函数中调用该命令。请注意,我们从不建议您在构造函数中调用任何内容。我们有 Initialize 方法。
原因是您使用TypeFactory构建 MainViewModel (Catel为您完成此操作)。然后在该线程中执行相同(异步)命令时,您希望实例化一个UnitOfWork,它也希望通过TypeFactory实例化一个类型。这是一个不同的主题。 TypeFactory仍处于锁定状态,因为您仍在构造MainViewModel。
同样,Catel在ViewModelBase上提供 Initialize 方法,该方法在创建时称为 outside ,因此可以安全地在那里做任何事情。请改用它。
答案 1 :(得分:2)
我想我知道可能是什么问题。如果我对问题的理解是正确的,下面的代码将重现它:
public partial class MainWindow : Window
{
class Model
{
Model() { }
public Task<int> AsyncTask { get; private set; }
public static Model Create()
{
var model = new Model();
Func<Task<int>> doTaskAsync = async () =>
{
await Task.Delay(1);
return 42;
};
model.AsyncTask = doTaskAsync();
return model;
}
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var textBlock = new TextBlock();
var window = new Window { Content = textBlock };
window.Loaded += (sIgnore, eIgnore) =>
{
// int result = ((Model)window.DataContext).AsyncTask.Result;
// textBlock.Text = result.ToString();
};
window.DataContext = Model.Create();
window.ShowDialog();
MessageBox.Show("Result: " +
((Model)window.DataContext).AsyncTask.Result);
}
}
取消注释注释行,window.Loaded
内的((Model)window.DataContext).AsyncTask.Result
事件处理程序中将出现死锁。
这是因为window.Loaded
在调度ShowDialog
的Dispatcher消息循环的同一次迭代上同步被触发。 AsyncTask
没有机会完成,因为await Task.Delay(1)
之后的继续安排在UI线程的DispatcherSynchronizationContext
上。
相同的AsyncTask.Result
代码会在ShowDialog
之后立即生效。这是因为在对话框关闭之前,已经执行了更多的消息循环迭代(在对话框的新Dispatcher框架上)。
修复很简单:
window.Loaded += async (sIgnore, eIgnore) =>
{
int result = await ((Model)window.DataContext).AsyncTask;
textBlock.Text = result.ToString();
};
这将在对话框的Dispatcher框架上异步完成任务。
我不确定这与OP的情况有多接近,因为在上述情况下放置await Task.Delay(1).ConfigureAwait(false)
也可以解决问题。然而,根据OP的代码,这是我可以做出的猜测。