小编C. *_*son的帖子

C# 中是否有一种方法可以在不使调用者也异步的情况下调用异步方法?

更清楚地说,我引用了一个以前不是异步的工厂方法。在最近的 API 升级中,他们淘汰了旧方法并创建了新的异步方法。现在,我们的代码库最初来自 VS2010,当时 async 还不存在。我想将方法​​调用更改为新版本,以便我们不会抛出弃用警告。

现在问题来了:对异步方法的任何调用似乎都需要“等待”,以保证该方法实际完成并且该方法中初始化的任何状态数据可用于后续操作。但是,在调用中放置“await”要求调用方法也是异步的,然后要求该方法的调用者也使用await,依此类推,一直到调用堆栈的顶部。我发现避免这种情况的唯一方法是将对异步工厂方法的调用放在 void 异步方法中。但是,Microsoft 已明确声明该功能仅适用于事件处理程序,否则应避免使用。

现在,我确实可以调整调用堆栈中的每个函数。但这不仅处理起来很烦人,而且还是一种极端的封装违规行为。为什么顶级类必须更改其方法头,因为对 27 层以下的函数的某些调用必须处理外部 API 更改?我怀疑我遗漏了一些非常明显的东西,但从它看起来的样子来看,我有两个选择:要么更改所有方法标头,要么接受“糟糕的编程实践”。还有其他方法吗?提前感谢您的任何意见。

c# asynchronous async-await

5
推荐指数
1
解决办法
976
查看次数

有没有一种方法可以用Moq来模拟DbSet.Find方法?

我目前正在使用扩展方法来将DbSets作为列表进行模拟:

    public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
    {
        var queryable = sourceList.AsQueryable();
        var mockDbSet = new Mock<DbSet<T>>();
        mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
        mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
        mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
        mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
        mockDbSet.Setup(x => x.Add(It.IsAny<T>())).Callback<T>(sourceList.Add);
        mockDbSet.Setup(x => x.Remove(It.IsAny<T>())).Returns<T>(x => { if (sourceList.Remove(x)) return x; else return null; } );

        return mockDbSet.Object;
    }
Run Code Online (Sandbox Code Playgroud)

但是,我想不出一种模拟Find方法的方法,该方法基于表的主键进行搜索。我可以在每个表的特定级别上执行此操作,因为我可以检查数据库,获取PK,然后仅模拟该字段的Find方法。但是我不能使用通用方法。

我想我也可以添加到EF自动生成的部分类中,以标记具有属性或某些内容的PK是哪个字段。但是我们有100多个表,如果您依靠人们手动维护此代码,那么它将使代码的管理更加困难。

EF6是否提供任何查找主键的方式,还是仅在连接到数据库后才动态知道?

c# generics entity-framework moq entity-framework-6

4
推荐指数
2
解决办法
2260
查看次数

为什么等待任务有时会阻止?

我想我对async/await对的工作方式有一般性的误解.我正在使用EasyNetQ方法(C#中的RabbitMQ接口),我正在尝试调用我创建的以下方法:

public Task<U> RequestDirectReply<T, U>(T request, int timeout) where T : class where U : class
{
    using (var bus = RabbitHutch.CreateBus($"virtualHost=MyVirtualHost;timeout={timeout};host=MyHostName"))
    {
        return bus.RequestAsync<T, U>(request);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我理解这一点的方式,我应该能够调用这个方法,从RequestAsync获取一个Task,然后做一堆东西,然后等待那个Task,一旦我完成了那些东西.像这样的东西:

Task<Reply> task = RequestDirectReply<Request, Reply>(msg, 10);

for (int i = 0; i < 1000000000; ++i)
{
    // Hi, I'm counting to a billion
}

var reply = await task;
Run Code Online (Sandbox Code Playgroud)

但是,程序会阻止对RequestAsync的调用超时,而不是等待.然后await会立即抛出超时异常.

为了看我是否误解,我也尝试了以下方法:

public async Task<U> RequestDirectReply<T, U>(T request, int timeout) where T : class where U : class
{
    using (var bus …
Run Code Online (Sandbox Code Playgroud)

c# async-await easynetq

2
推荐指数
1
解决办法
420
查看次数