我有一个简单的类来做同步的事情,
<telerik:GridTemplateColumn UniqueName="AccountCode" HeaderText="Account Code">
<ItemTemplate>
<asp:Label ID="lblAcCode" runat="server" Text='<%# Eval("AccountCode")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:Label ID="lblAcCode2" runat="server" Text='<%# Eval("AccountCode") + " - " + Eval("AccountDescription")%>' Visible="false"></asp:Label>
<telerik:RadComboBox ID="ddlAccountCode" runat="server" Height="200" Width="240" DropDownWidth="310" HighlightTemplatedItems="true" CausesValidation="true"
OnItemsRequested="ddlAccountCode_ItemsRequested" EnableItemCaching="true" ShowDropDownOnTextboxClick="false" EnableLoadOnDemand="True" ShowMoreResultsBox="true" EnableVirtualScrolling="true" MarkFirstMatch="True" AllowCustomText="true"
Filter="Contains" AppendDataBoundItems="true" DataTextField="AccountDescription" DataValueField="AccountCodeID" AutoPostBack="true" OnSelectedIndexChanged="ddlAccountCode_SelectedIndexChanged">
</telerik:RadComboBox>
<telerik:RadButton id="btnSearch" runat="server" text="Search" OnClick="btnSearch_Click">
</telerik:RadButton>
</EditItemTemplate>
</telerik:GridTemplateColumn>
显然,这段代码没有完全定义,但确实说明了我的问题。
现在,类RadComboBox
和public static class Synchronous
{
public static void DoTheWholeThing()
{
AStuff aStuff;
using (var a = new A())
{
aStuff = a.GetStuff();
}
BStuff bStuff;
using (var b = new B())
{
bStuff = b.GetStuff();
}
var combination = CombineStuff(aStuff, bStuff);
}
private static Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
都负责从不同的远程源检索数据。因此,A
和B
的开发人员已经实现了名为A
的异步入口点,它们分别返回B
和GetStuffAsync
。
我想最大限度地利用异步方法并同时调用它们,这样我就可以减少代码的整体等待时间。
到目前为止,这是我编造的内容。
Task<AStuff>
除了这个代码好奇地看起来像javascript模块模式,这是正确的方法。我不认为我应该使用Task.Run
,因为此代码为clearly not CPU bound。
似乎有点&#34;笨拙&#34;我需要实例化类型代理来执行此操作。还有更好的方法吗?
以下两个好的答案我在命名函数和延续之间陷入困境。
答案 0 :(得分:3)
当您简单地将匿名方法提取到命名方法时,代码变得非常简单:
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var getAStuffTask = GetAStuffAsync(cancellationToken);
var getBStuffTask = GetBStuffAsync(cancellationToken);
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
private static async Task<AStuff> GetAStuffAsync(CancellationToken cancellationToken)
{
using (var a = new A())
{
return await a.GetStuffAsync(cancellationToken);
}
}
private static async Task<BStuff> GetBStuffAsync(CancellationToken cancellationToken)
{
using (var b = new B())
{
return await b.GetStuffAsync(cancellationToken);
}
}
那就是说,如果真的想要坚持使用匿名方法,你可以创建一个帮助方法,允许泛型类型推断和lambdas隐式地找出委托的类型:
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var getAStuffTask = Start(async () =>
{
using (var a = new A())
{
return await a.GetStuffAsync(cancellationToken);
}
});
var getBStuffTask = Start(async () =>
{
using (var b = new B())
{
return await b.GetStuffAsync(cancellationToken);
}
});
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
public static Task<T> Start<T>(Func<Task<T>> asyncOperation)
{
return asyncOperation();
}
答案 1 :(得分:3)
一旦任务完成,请使用TPL延续来调用Dispose
。
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var a = new A();
var b = new B();
// start the tasks and store them for awaiting later
var getAStuffTask = a.GetStuffAsync(cancellationToken);
var getBStuffTask = b.GetStuffAsync(cancellationToken);
// queue up continuations to dispose of the resource as soon as it is not needed
getAStuffTask.ContinueWith(() => a.Dispose());
getBStuffTask.ContinueWith(() => b.Dispose());
// await as normal
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
我不确定将整个方法包装在附加using
块中是否可以完成任何操作,但它可以让您高枕无忧。
答案 2 :(得分:1)
您不需要在代理中包装异步调用以使它们立即执行。如果直接调用$(function() {
$('.component-individual-detail-profile').each(function() {
var $self = $(this), $images = $self.find('.photos');
$images.find('li').click(function(e) {
e.preventDefault();
var thumb = $(this);
$images.find('.selected')
.attr('src', thumb.find('img').attr('src'))
.attr('alt', thumb.find('img').attr('alt'))
.attr('title', thumb.find('img').attr('title'));
});
});
});
方法而不等待它们,则会得到相同的结果。
GetStuffAsync
请注意,这会在调用public static class Asynchronous
{
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
using (var a = new A())
using (var b = new B()) {
var taskA = a.GetStuffAsync(cancellationToken);
var taskB = b.GetStuffAsync(cancellationToken);
await Task.WhenAll(new [] { taskA, taskB });
var combination = CombineStuff(taskA.Result, taskB.Result);
}
}
private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
期间将a
和b
对象保持为@Servy备注。如果这是一个问题,CombineStuff
对象的声明可以移到Task
块之外,如下所示:
using
虽然只要两个任务都在运行,这仍然适用于public static class Asynchronous
{
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
Task taskA;
Task taskB;
using (var a = new A())
using (var b = new B()) {
taskA = a.GetStuffAsync(cancellationToken);
taskB = b.GetStuffAsync(cancellationToken);
await Task.WhenAll(new [] { taskA, taskB });
}
var combination = CombineStuff(taskA.Result, taskB.Result);
}
private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
和a
,而不是在它们返回时处理每个任务。