C# 在C中并行运行多个操作#

C# 在C中并行运行多个操作#,c#,task-parallel-library,.net-4.5,C#,Task Parallel Library,.net 4.5,我在ASP.NETWebForms页面中有以下代码,它基本上检查缓存中是否有某个值,如果没有,则调用一个方法获取数据,然后将其存储在缓存中。获取数据的方法如下所示 ChartRenderingHelper.GenerateBidsStatusCreated(currYear.ToString(), currQuarter.ToString(), currYearType.ToString()) 使用EF调用存储的进程,这3个调用全部调用单独的SP。现在我按顺序执行,因此,如果每个SP需要5秒,

我在ASP.NETWebForms页面中有以下代码,它基本上检查缓存中是否有某个值,如果没有,则调用一个方法获取数据,然后将其存储在缓存中。获取数据的方法如下所示

ChartRenderingHelper.GenerateBidsStatusCreated(currYear.ToString(), currQuarter.ToString(), currYearType.ToString())
使用EF调用存储的进程,这3个调用全部调用单独的SP。现在我按顺序执行,因此,如果每个SP需要5秒,则整个操作需要15秒。我正在考虑使用一些任务并行运行这些进程,但不确定如何更改当前代码来实现这一点

  bidsCreated.Value = DashboardCacheHelper.IsIncache(bidsCreatedKey, useCaching) ? DashboardCacheHelper.GetFromCache(bidsCreatedKey) : (string)DashboardCacheHelper.SaveCache(bidsCreatedKey, JsonConvert.SerializeObject(ChartRenderingHelper.GenerateBidsStatusCreated(currYear.ToString(), currQuarter.ToString(), currYearType.ToString())), DateTime.Now.AddDays(cacheDays));
            bidsSubmitted.Value = DashboardCacheHelper.IsIncache(bidsSubmittedKey, useCaching) ? DashboardCacheHelper.GetFromCache(bidsSubmittedKey) : (string)DashboardCacheHelper.SaveCache(bidsSubmittedKey, JsonConvert.SerializeObject(ChartRenderingHelper.GenerateBidsStatusSubmitted(currYear.ToString(), currQuarter.ToString(), currYearType.ToString())), DateTime.Now.AddDays(cacheDays));
            bidsClosed.Value = DashboardCacheHelper.IsIncache(bidsClosedKey, useCaching) ? DashboardCacheHelper.GetFromCache(bidsClosedKey) : (string)DashboardCacheHelper.SaveCache(bidsClosedKey, JsonConvert.SerializeObject(ChartRenderingHelper.GenerateBidsStatusClosed(currYear.ToString(), currQuarter.ToString(), currYearType.ToString())), DateTime.Now.AddDays(cacheDays));
我怎样才能同时完成这3项作业?使用TPL,我知道我们可以并行运行方法

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());

这是推荐的方法吗?如果我说有12个操作需要并行运行,那么所有使用EF调用SQL存储的过程都将是性能上的问题。

您可以使用异步来实现这一点,但是最好使用实体框架代码的异步实现来添加和获取

首先,我通过引入一个方法
GetOrAddAsync
,对代码进行了重构,以减少重复并使其更具可读性,该方法接受缓存键、
useCaching
(这是干什么用的?)的布尔值以及
ChartRenderingHelper
方法的委托。目前还不清楚是什么类型的
currQuarter
currYearType

private async Task<string> GetOrAddAsync(string cacheKey, bool useCaching, int cacheDays, DateTime currYear, ? currQuarter, ? currYearType, Action<string, string, string> cacheFactory)
{
    if(DashboardCacheHelper.IsIncache(cacheKey, useCaching))
    {
        return DashboardCacheHelper.GetFromCache(cacheKey);
    }

    return (string)(await DashboardCacheHelper.SaveCacheAsync(bidsClosedKey, JsonConvert.SerializeObject(cacheFactory(currYear.ToString(), currQuarter.ToString(), currYearType.ToString())), DateTime.Now.AddDays(cacheDays)).ConfigureAwait(false))
}
需要记住的一件关键事情是将调用方法标记为
async
,如果它是一个事件处理程序,那么它将是
async void
——但请记住,在任何不是事件处理程序的方法中,
async void
,因为您被限制为带有事件处理程序的
void
返回类型


正如LeBigCat在评论中指出的那样,
ConfigureAwait
应该与在.NET Framework上运行的异步代码一起使用,以防止死锁,请阅读了解原因。

您可以使用,然后。@sanisinghhutunen EF有异步方法,因此您不需要
任务。运行
,OP使用ASP.Net所以
任务。WaitAll
将导致死锁-不确定您的建议是积极的邪恶还是只是…没有经过深思熟虑?不要在ASP.Net页面中直接使用并行,因为线程可能会在未完成作业的情况下挂起,并且它不能正确使用
异步
方法。我将添加ConfigureWait(错).OP还需要确保他要写入缓存的数据是线程安全的。他使用的是web表单页面。我确实意识到,在我发布了该评论以及
.net-4.5
标记后。更新了代码。要将其包含在我的页面加载函数中,我已将其标记为异步。我希望这样就可以了,如果它是事件处理程序,那么
 async void
,否则如果它有返回类型,它将是
异步任务
var bidsCreatedCacheTask = GetOrAddAsync(bidsCreatedKey, useCaching, cacheDays, currYear, currQuarter, currYearType, ChartRenderingHelper.GenerateBidsStatusCreated);
var bidsSubmittedCacheTask = GetOrAddAsync(bidsSubmittedKey, useCaching, cacheDays, currYear, currQuarter, currYearType, ChartRenderingHelper.GenerateBidsStatusSubmitted);
var bidsClosedCacheTask = GetOrAddAsync(bidsClosedKey, useCaching, cacheDays, currYear, currQuarter, currYearType, ChartRenderingHelper.GenerateBidsStatusClosed);

await Task.WhenAll(bidsCreatedCacheTask, bidsSubmittedCacheTask, bidsClosedCacheTask).ConfigureAwait(false);

bidsCreated.Value = await bidsCreatedCacheTask;
bidsSubmitted.Value = await bidsSubmittedCacheTask;
bidsClosed.Value = await bidsClosedCacheTask;