我需要从mvc应用程序调用第三方异步方法。此异步方法的名称为ForceClient.QueryAsync。它来自一个开放源代码项目:https://github.com/developerforce/Force.com-Toolkit-for-NET/。
下面的模型正常工作。当进程处于mvc的View阶段时,机会包含预期的信息:
public async Task<ActionResult> MyController(string Id) {
. . . .
MyModel model = new MyModel();
var client = new ForceClient(instanceUrl, accessToken, apiVersion);
var qry = await client.QueryAsync<MyModel.SFOpportunity>(
"SELECT Name, StageName FROM Opportunity where Id='" + Id + "'");
model.Opportunity = qry.Records.FirstOrDefault();
. . . .
return View(viewName, myModel);
}
但是下面的方法不起作用。当流程处于View阶段时,model.Opportunity为null。我做了一些调试,发现流程是这样的:
1)第1步
2)第2步
3)在查看阶段。此时,model.Opportunity为空,我需要填充它。
4)第三步。
public async Task<ActionResult> MyController(string Id) {
. . . .
MyModel myModel = await Task.Run(() =>
{
var result = new MyModel(Id);
return result;
}); // =====> Step 1
. . . .
return View(viewName, myInfoView);
}
public class MyModel
{
public SFOpportunity Opportunity { get; set; }
public MyModel(string id)
{
setOpportunityAsync(id);
}
private async void setOpportunityAsync(string id)
{
. . .
var client = new ForceClient(instanceUrl, accessToken, apiVersion);
var qry = await client.QueryAsync<MyModel.SFOpportunity>(
"SELECT Name, StageName FROM Opportunity where Id='" + id + "'"); // ======> Step2
Opportunity = qry.Records.FirstOrDefault(); // =====> step3
}
所以,我的问题是我需要做什么才能使其按以下顺序执行步骤: 1)Step1
2)第2步
3)第三步
4)在查看阶段。此时,应该填充模型。
答案 0 :(得分:1)
MyModel
的构造函数不会(也不能)等待setOpportunityAsync
,因为构造函数本身不是(也不能是)异步的。否则,您将可以等待对构造函数本身的调用,但不能。因此,异步方法可能不会在调用构造函数后立即完成执行。它将完成...只要完成就可以。
这里有一个较小的测试类来说明行为:
public class HasConstructorWithAsyncCall
{
public HasConstructorWithAsyncCall()
{
MarkConstructorFinishedAsync();
}
public bool ConstructorHasFinished { get; private set; }
async void MarkConstructorFinishedAsync()
{
await Task.Delay(500);
ConstructorHasFinished = true;
}
}
构造实例后,ConstructorHasFinished
的值是什么?这是单元测试:
[TestMethod]
public void TestWhenConstructorFinishes()
{
var subject = new HasConstructorWithAsyncCall();
Assert.IsFalse(subject.ConstructorHasFinished);
Thread.Sleep(600);
Assert.IsTrue(subject.ConstructorHasFinished);
}
测试通过。 MarkConstructorFinishedAsync
尚未完成时,构造函数将返回,因此ConstructorHasFinished
为false。半秒钟后它结束,并且值为true。
您无法标记构造函数async
,因此无法await
构造函数中的任何内容。
通常,我们不会将任何长期运行的东西(例如数据检索)放入构造函数中,包括我们会异步调用的任何东西。如果这样做,则必须同步调用它,或者知道构造函数的完成并不意味着它是完全“构造的”。
答案 1 :(得分:1)
您不能拥有async
构造函数。
One alternative is to have async
factory methods:
public class MyModel
{
public SFOpportunity Opportunity { get; set; }
private MyModel() { }
public static async Task<MyModel> CreateAsync(string id)
{
var result = new MyModel();
await result.setOpportunityAsync(id);
return result;
}
private async Task setOpportunityAsync(string id)
{
...
}
}