C# ShowDialog中的Catel async wait命令-死锁

C# ShowDialog中的Catel async wait命令-死锁,c#,mvvm,task-parallel-library,async-await,catel,C#,Mvvm,Task Parallel Library,Async Await,Catel,使用库Сatel最新版本(3.8.1 beta) 如何使用对话框窗口中的点击方法 例如。 在主视图模型中调用方法 private bool ShowDialogWindow() { var typeFactory = TypeFactory.Default ; var vm = typeFactory.CreateInstanceWithParametersAndAutoCompletion<LoginWindowViewModel>(); return _u

使用库Сatel最新版本(3.8.1 beta)

如何使用对话框窗口中的点击方法

例如。 在主视图模型中调用方法

private bool ShowDialogWindow()
{
    var typeFactory = TypeFactory.Default ;
    var vm = typeFactory.CreateInstanceWithParametersAndAutoCompletion<LoginWindowViewModel>();
    return _uiVisualizerService.ShowDialog(vm) ?? false;
}
private bool ShowDialogWindow()
{
var typeFactory=typeFactory.Default;
var vm=typeFactory.CreateInstanceWithParameters和AutoCompletion();
返回_uivisualerservice.ShowDialog(vm)??false;
}
在LoginWindowViewModel中,我有一个名为method的命令(也可以尝试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 a=等待任务.工厂.开始新(()=>
{
使用(var uow=new UnitOfWork())
{
var userRep=uow.GetRepository();
userRep.GetAll();
返回5;
}
});
a++;
返回a;
}
只有在关闭对话框窗口时,我才从等待的方法获得结果。 锁出现在第行

var uow=新的UnitOfWork()

ConfigureWait(false)-无助于解决问题

当我删除UnitOfWork时-方法有效

当我将方法代码更改为 var d=TypeFactory.Default.CreateInstanceWithParameters(); 返回5

分块也在TypeFactory上复制

根据对话框中不允许的服务类别,注意:我编辑了此答案,因此它包含此问题的答案。前面的答案包含了一些提示,让话题发起者调查这个问题

在MainViewModel的构造函数中调用该命令。请注意,我们从不建议您调用构造函数中的任何内容。我们有初始化方法

原因是您使用TypeFactory构建MainViewModel(Catel为您这样做)。然后,在该线程中执行的同一个(异步)命令中,您希望实例化UnitOfWork,该UnitOfWork还希望通过TypeFactory实例化类型。这是在另一个线程上。TypeFactory仍处于锁定状态,因为您仍在构造MainViewModel

同样,Catel在ViewModelBase上提供了Initialize方法,该方法在创建外部调用,因此在其中执行任何操作都是安全的。请改用它。

我想我知道这里可能有什么问题。如果我对该问题的理解是正确的,则以下代码将复制该问题:

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);
    }
}
这将异步完成对话框的Dispatcher框架上的任务


我不确定这与OP的场景有多接近,因为放置
wait Task.Delay(1).configurewait(false)
也可以解决上述情况下的问题。然而,这是我根据OP的代码所能猜测的范围。

那么你的
UnitOfWork
构造函数是做什么的呢?你有没有调试过它在其中的位置?我看不出有任何明显的问题…我看不到锁。我认为这里的要点并不完全在于unitofwork作为访问配置或依赖解决方案的机制,你说的“锁出现了”——这表明它是锁定(挂起的)。那么,如果在锁定代码时破译代码,堆栈跟踪会是什么样子呢?我也不清楚这两个不同的代码段是如何相互关联的;a、 处置();返回5//工作!但是UnitOfWork=>DeadLock Last Line output window[DEBUG][Catel.IoC.ServiceLocator]将类型“Catel.Data.IConnectionStringManager”注册为类型“Catel.Data.ConnectionStringManager”,我在Initialize方法(在View.Loaded事件中调用)和作为命令中都尝试过,两者都可以很好地使用以下代码:public async Task Test(字符串登录,字符串密码){var a=wait Task.Factory.StartNew(()=>{using(var-uow=new UnitOfWork()){var-userRep=uow.GetRepository();userRep.GetAll();return 5;}});a++;return a;}请创建一个可复制的应用程序(尽可能小)在官方的问题跟踪程序中,问题是他说他是在命令中完成的。我曾尝试使用DbContext和UnitOfWork/Repository复制它,但无法将其挂起(在Initialize(View.Loaded)和作为命令)@GeertvanHorrik,这个命令只是另一种事件。如果它是同步触发的,在
ShowDialog
进入模式消息循环之前的某个地方,效果是一样的。据我所知,他显示了登录窗口,在登录窗口内他执行了调用登录调用的命令(这是异步的).但他应该简单地提出一个好的可复制案例。@GeertvanHorrik,我同意。到目前为止,我们只能猜测。仅供参考:我们发现了问题。TypeFactory上存在多线程死锁。请参阅其他答案。
window.Loaded += async (sIgnore, eIgnore) =>
{
    int result = await ((Model)window.DataContext).AsyncTask;
    textBlock.Text = result.ToString();
};