【问题标题】:using dependency properties along with async ctp使用依赖属性和异步 ctp
【发布时间】:2012-11-26 23:23:58
【问题描述】:

我创建了一些示例 ViewModel 来测试使用 asyncCtp 的 DP:

public class SampleVm : DependencyObject
{

    public static readonly DependencyProperty SampleDependencyPropertyProperty =
        DependencyProperty.Register("SampleDependencyProperty", typeof (int), typeof (SampleVm), new PropertyMetadata(default(int)));

    public int SampleDependencyProperty
    {
        get { return (int) GetValue(SampleDependencyPropertyProperty); }
        set { SetValue(SampleDependencyPropertyProperty, value); }
    }
    public ISampleModel _model;
    public SampleVm(ISampleModel model)
    {
        _model = model;
    }

    public async Task SetDependencyProperty()
    {
        var modelData = await TaskEx.Run(() => _model.GetSomeIntegerValue());
        SampleDependencyProperty = modelData;
    }
}

注入到 ViewModel 的模型是:

public interface ISampleModel
{
    int GetSomeIntegerValue();
}

public class SampleModel : ISampleModel
{
    public int GetSomeIntegerValue()
    {
        return 10;
    }
}

当我运行 WPF 应用程序时没有问题,但是当我想用以下代码对其进行测试时:

[Fact]
public async Task CheckValueSetting()
{
    var model = new Mock<ISampleModel>();
    model.Setup(x => x.GetSomeIntegerValue()).Returns(5);
    var viewModel =new SampleVm(model.Object);

    await viewModel.SetDependencyProperty();

    Assert.Equal(5, viewModel.SampleDependencyProperty);
}

我收到以下错误:

System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.

Server stack trace: 

    at System.Windows.Threading.Dispatcher.VerifyAccess()
    at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
    at WpfApplication4.SampleVm.set_SampleDependencyProperty(Int32 value) in SampleVM.cs: line 19
    at WpfApplication4.SampleVm.<SetDependencyProperty>d__1.MoveNext() in SampleVM.cs: line 30

    Exception rethrown at [0]: 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
    at WpfApplication4.SampleVmFixture.<CheckValueSetting>d__0.MoveNext() in SampleVmFixture.cs: line 16 

那么解决办法是什么?

【问题讨论】:

  • 我可以检查一下:你为什么还在使用异步 CTP?现在这不是核心 .NET 的全部内容吗?
  • 由于公司的限制,我必须使用.Net framework 4。
  • 这完全没有意义。根据定义,CTP 完全不受支持,在这种情况下,现在已过时。没有比面对升级更好的选择了。 IMO:进行升级(即使这意味着在内部进行一些工作),或者忘记异步。最后:无论如何,大部分异步内容都在 4.0 中!!!
  • 以 .NET 4 为目标是有道理的,特别是因为“就地”4.5 升级不支持 XP。他可能只是不知道 Microsoft.Bcl.Async。
  • 感谢@MarcGravell 和 StephenCleary 的建议。在阅读了这个question 和这个blog on MSDN 之后,我认为解决方案不是继续使用AsyncCtp。

标签: c# mvvm async-ctp xunit.net


【解决方案1】:

首先,我建议您使用Microsoft.Bcl.Async package 升级到VS2012。这将使您能够使用最新工具以 .NET 4.0 为目标。 Async CTP 存在无法修复的已知错误,并且存在安装问题(无法修复),这将使设置新的开发机器变得相当困难。

但在删除 Async CTP 之前,请查看 Async CTP 目录下的 (C# Testing) Unit Testing 目录。你会发现有几种类型可以帮助进行单元测试,例如GeneralThreadAffineContext

[Fact]
public async Task CheckValueSetting()
{
    var model = new Mock<ISampleModel>();
    model.Setup(x => x.GetSomeIntegerValue()).Returns(5);
    SampleVm viewModel;
    await GeneralThreadAffineContext.Run(async () =>
    {
        viewModel = new SampleVm(model.Object);
        await viewModel.SetDependencyProperty();
    });

    Assert.Equal(5, viewModel.SampleDependencyProperty);
}

【讨论】:

  • CTP 中的示例在其他地方不可用?另外,我想你忘了await Run() 的结果。
  • 我不知道异步 CTP 的“附加”的官方来源;我的 AsyncEx 库中的 AsyncContextGeneralThreadAffineContext 非常接近,但我不知道有任何相当于 WindowsFormsContextWpfContext 的东西。此外,Run 返回 void(直到所有 async 方法完成后才会完成)。
  • GeneralThreadAffineContext 我有几个重载的Run()void Run(Action asyncAction)Task Run(Func&lt;Task&gt; asyncMethod),因为你使用的是第二个,我认为你必须await 它。
  • @svick:你是对的;我修改了我的副本。从技术上讲,Run 重载将等待async 方法完成,但await 执行它并没有什么坏处。
猜你喜欢
  • 2020-05-27
  • 2011-08-19
  • 1970-01-01
  • 2018-03-26
  • 2011-08-05
  • 2013-05-25
  • 1970-01-01
  • 2013-05-10
  • 1970-01-01
相关资源
最近更新 更多