Tag: async await

如何使两个SQL查询真正异步

我的问题是基于一个真正的项目问题,但我从来没有使用过System.Threading.Tasks库或执行任何涉及线程的严肃编程,所以我的问题可能是缺乏关于特定库的知识以及对异步的更普遍的误解真的意味着在编程方面。 所以我的真实情况就是这个 – 我需要获取有关用户的数据。 在我目前的情况下,它是财务数据,所以假设我需要特定用户的所有Accounts ,所有Deposits和所有Consignations 。 在我的情况下,这意味着查询每个属性的数百万条记录,并且每个查询本身相对较慢,但是获取Accounts比获取Deposits慢几倍。 所以我为我要使用的三种银行产品定义了三个类,当我想获取某些用户的所有银行产品的数据时,我做了类似这样的事情: List accounts = GetAccountsForClient(int clientId); List deposits = GetDepositsForClient(int clientId); List consignations = GetConsignationsForClient(int clientId); 所以问题从这里开始我需要同时获取所有这三个列表,因为我要将它们传递给我显示所有用户数据的视图。 但正如现在一样,执行是同步的(如果我在这里正确使用这个术语),那么收集所有三种产品的数据的总时间是: Total_Time = Time_To_Get_Accounts + Time_To_Get_Deposits + Time_To_Get_Consignations 这不好,因为每个查询都比较慢,所以总时间很长,而且, accounts查询比其他两个查询花费的时间要多得多,所以今天进入我脑海的想法是 – “如果我能做什么同时执行此查询“。 也许这是我对这个主题最大的误解,但对我来说,最接近这个想法是让它们异步,所以也许Total_Time不会是最慢查询的时间,但是会比所有三个查询的总和快得多。 由于我的代码很复杂,我创建了一个简单的用例,我认为,反映了我想要做的很好。 我有两种方法: public static async Task GetAccounts() { int total1 = 0; using (SqlConnection connection = new […]

在IEnumerable.Select中调用异步方法

我有以下代码,使用异步方法在类型R和L之间转换项目: class MyClass { public async Task MyMethodAsync(List remoteItems) { … List mappedItems = new List(); foreach (var remoteItem in remoteItems ) { mappedItems.Add(await MapToLocalObject(remoteItem)); } //Do stuff with mapped items … } private async Task MapToLocalObject(R remoteObject); } 这是否可以使用IEnumerable.Select调用(或类似)来减少代码行? 我试过这个: class MyClass { public async Task MyMethodAsync(List remoteItems) { … List mappedItems = remoteItems.Select(async […]

在TryReceiveAll之后使用OutputAvailableAsync的BufferBlock死锁

在处理这个问题 的答案时 ,我写了这个片段: var buffer = new BufferBlock(); var producer = Task.Run(async () => { while (true) { await Task.Delay(TimeSpan.FromMilliseconds(100)); buffer.Post(null); Console.WriteLine(“Post ” + buffer.Count); } }); var consumer = Task.Run(async () => { while (await buffer.OutputAvailableAsync()) { IList items; buffer.TryReceiveAll(out items); Console.WriteLine(“TryReceiveAll ” + buffer.Count); } }); await Task.WhenAll(consumer, producer); 生产者应该每100毫秒将项目发布到缓冲区,并且消费者应该清除缓冲区中的所有项目并异步地等待更多项目显示。 实际发生的是生产者清除所有项目一次,然后再也不会超出OutputAvailableAsync 。 如果我切换消费者逐个删除项目,它将作为例外工作: […]

为什么LogicalCallContext无法与异步一起使用?

在这个问题中,Stephen Cleary接受的答案是LogicalCallContext无法与async一起正常工作。 他还在这个 MSDN主题中发布了它。 LogicalCallContext保持Hashtable存储发送到CallContext.LogicalGet / SetData的数据。 它只是这个Hashtable的浅层副本。 因此,如果您在其中存储可变对象,则不同的任务/线程将看到彼此的更改。 这就是Stephen Cleary的示例NDC程序(在MSDN线程上发布)无法正常工作的原因。 但是AFAICS,如果你只在Hashtable中存储不可变数据(可能通过使用不可变集合 ),那应该有效,让我们实现一个NDC。 然而,Stephen Cleary也在接受的答案中说: CallContext不能用于此。 Microsoft特别建议不要使用CallContext进行远程处理以外的任何操作。 更重要的是,逻辑CallContext不了解异步方法如何提前返回并稍后恢复。 不幸的是,该建议的链接已关闭(找不到页面)。 所以我的问题是,为什么不推荐这个? 为什么我不能以这种方式使用LogicalCallContext? 说它不理解异步方法是什么意思? 从调用者的POV来看,他们只是返回任务的方法,不是吗? ETA:另见其他问题 。 在那里,Stephen Cleary的答案说: 你可以使用CallContext.LogicalSetData和CallContext.LogicalGetData,但我建议你不要,因为当你使用简单的并行性时它们不支持任何类型的“克隆” 这似乎支持我的情况。 所以我应该能够建立一个NDC,这实际上是我需要的,而不是log4net。 我写了一些示例代码,它似乎工作,但仅仅测试并不总是捕获并发错误。 所以,由于其他post中有提示这可能不起作用,我仍然会问:这种方法有效吗? ETA:当我从下面的答案中运行斯蒂芬提出的复制品时,我没有得到错误的答案,他说我会,我得到正确的答案。 即使他说“这里的LogicalCallContext值总是”1“”,我总是得到0的正确值。这可能是因为竞争条件? 无论如何,我还没有在我自己的电脑上复制任何实际问题。 这是我正在运行的确切代码; 它只在这里打印“真实”,斯蒂芬说它至少应该在某些时候打印“假”。 private static string key2 = “key2”; private static int Storage2 { get { return (int) CallContext.LogicalGetData(key2); } set […]

是否可以在非异步方法中调用等待方法?

在C#/ XAML的Windows 8应用程序中,我有时想从非异步方法调用一个等待的方法。 实际上更换它是正确的: public async Task MyCallingMethod() { string result = await myMethodAsync(); return result; } 这样 : public string MyCallingMethod() { Task.Run(async () => { string result = await myMethodAsync(); return result; }); } 对我来说的好处是我可以在没有等待的情况下使用MyCallingMethod,但这是正确的吗? 如果我想为MyCallingMethod传递ref参数,这可能是一个优点,因为在异步方法中不可能有ref参数。

不使用异步方法更新Struct的私有字段值

我刚刚在结构中使用异步方法遇到了一个奇怪的行为。 有人可以解释为什么会发生这种情况,最重要的是如果有解决方法吗? 这是一个简单的测试结构,仅仅是为了演示问题 public struct Structure { private int _Value; public Structure(int iValue) { _Value = iValue; } public void Change(int iValue) { _Value = iValue; } public async Task ChangeAsync(int iValue) { await Task.Delay(1); _Value = iValue; } } 现在,让我们使用该结构并执行以下调用 var sInstance = new Structure(25); sInstance.Change(35); await sInstance.ChangeAsync(45); 第一行实例化结构, sInstance._Value值为25 。 第二行更新sInstance._Value值,它变为35 。 现在第三行没有做任何事情,但我希望它将sInstance._Value值更新为45但是sInstance._Value保持35 […]

何时缓存任务?

我正在观看异步的禅:最佳性能的最佳实践和Stephen Toub开始谈论任务缓存,而不是缓存任务作业的结果,你自己缓存任务。 据我所知,为每项工作开始一项新任务是昂贵的,应尽量减少。 在28:00左右,他展示了这种方法: private static ConcurrentDictionary s_urlToContents; public static async Task GetContentsAsync(string url) { string contents; if(!s_urlToContents.TryGetValue(url, out contents)) { var response = new HttpClient().GetAsync(url); contents = response.EnsureSuccessStatusCode().Content.ReadAsString(); s_urlToContents.TryAdd(url, contents); } return contents; } 首先看起来像是一个很好的思考方法,你缓存结果,我没有考虑缓存获取内容的工作。 而且他展示了这种方法: private static ConcurrentDictionary<string, Task> s_urlToContents; public static Task GetContentsAsync(string url) { Task contents; if(!s_urlToContents.TryGetValue(url, out contents)) { contents […]

在Dispatcher.BeginInvoke()中使用async / await

我有一个方法与一些代码执行await操作: public async Task DoSomething() { var x = await …; } 我需要在Dispatcher线程上运行该代码。 现在, Dispatcher.BeginInvoke()是等待的,但是我无法将lambda标记为async以便从内部运行await ,如下所示: public async Task DoSomething() { App.Current.Dispatcher.BeginInvoke(async () => { var x = await …; } ); } 在内部async ,我得到错误: 无法将lambda表达式转换为类型’System.Delegate’,因为它不是委托类型。 如何在Dispatcher.BeginInvoke()使用async ?

异步库最佳实践:ConfigureAwait(false)与设置同步上下文

众所周知,在通用库中,应在每次await调用时使用ConfigureAwait(false)以避免继续当前的SynchronizationContext。 作为使用ConfigureAwait(false)来编写整个代码库的替代方法,可以在公共表面方法中将SynchronizationContext设置为null一次,并在返回给用户之前将其恢复。 换一种说法: public async Task SomeSurfaceMethod() { var callerSyncCtx = SynchronizationContext.Current; SynchronizationContext.SetSynchronizationContext(null); try { // Do work } finally { SynchronizationContext.SetSynchronizationContext(callerSyncCtx); } } 这也可以包含在using以获得更好的可读性。 这种方法是否有缺点,它最终不会产生相同的效果吗? 主要优点显然是可读性 – 删除所有ConfigureAwait(false)调用。 它还可以降低在某处忘记ConfigureAwait(false)的可能性(虽然分析器可以减轻这种情况,但可以说开发人员也可以忘记更改SynchronizationContext)。 一个有点奇特的优点是没有嵌入在所有方法中捕获SynchronizationContext的选择。 换句话说,在一种情况下,我可能想要使用SynchronizationContext运行方法X,而在另一种情况下,我可能希望在没有一个的情况下运行相同的方法。 当ConfigureAwait(false)嵌入到无法实现的任何地方时。 当然,这是一个非常罕见的要求,但我在处理Npgsql时遇到了这个问题(触发了这个问题)。

如何在mvvmcross视图模型中使用async?

我在mvvmcross viewmodel中有一个长时间运行的进程,并希望将其设置为异步( http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx )。 Xamarin的测试版渠道目前支持async关键字。 下面是我目前如何实现异步的示例。 IsBusy标志可以绑定到UI元素并显示加载消息。 这是正确的方法吗? public class MyModel: MvxViewModel { private readonly IMyService _myService; private bool _isBusy; public bool IsBusy { get { return _isBusy; } set { _isBusy = value; RaisePropertyChanged(() => IsBusy); ; } } public ICommand MyCommand { get { return new MvxCommand(DoMyCommand); } } public MyModel(IMyService myService) { […]