私はTAPとasync/newを実際にC#に入れていますので、ここで悪いコードの匂いがするかもしれません。 :-)MVCコントローラからの非同期呼び出しを含むサービスを呼び出すための正しいパターン
私は次のように見えるサービスメソッドがあります。
public OzCpAddOrUpdateEmailAddressToListOutput AddOrUpdateEmailAddressToList(
OzCpAddOrUpdateEmailAddressToListInput aParams)
{
var result = new OzCpAddOrUpdateEmailAddressToListOutput();
try
{
var mailChimManager = new MailChimpManager(aParams.MailChimpApiKey);
Task<Member> mailChimpResult =
mailChimManager.Members.AddOrUpdateAsync(
aParams.Listid,
new Member
{
EmailAddress = aParams.EmailAddress
});
//Poll async task until it completes.
//Give it at most 8 seconds to do what it needs to do
var outOfTime = DateTime.Now.AddSeconds(8);
while (!mailChimpResult.IsCompleted)
{
if (DateTime.Now > outOfTime)
{
throw new Exception("Timed out waiting for MailChimp API.");
}
}
//Should there have been a problem with the call then we raise an exception
if (mailChimpResult.IsFaulted)
{
throw new Exception(
mailChimpResult.Exception?.Message ??
"Unknown mail chimp library error.",
mailChimpResult.Exception);
}
else
{
//Call to api returned without failing but unless we have
//the email address subscribed we have an issue
if (mailChimpResult.Result.Status != Status.Subscribed)
{
throw new Exception(
$"There was a problem subscribing the email address
{aParams.EmailAddress} to the mailchimp list id
{aParams.Listid}");
}
}
}
catch (Exception ex)
{
result.ResultErrors.AddFatalError(PlatformErrors.UNKNOWN, ex.Message);
}
return result;
}
をしかし、私はMVCコントローラアクションmailChimpResult.IsCompleted
から呼び出すときは常にfalse
を返し、最終的に私はタイムアウトを打ちます。
これは、HttpClient IsComplete always return falseのように非同期呼び出しを連鎖していないためであり、異なるスレッドのためにこの動作が「期待」されているためです。
私は私のサービスメソッドは、それが何をしているかのasync
自然の複雑さを隠し、単につまり、私のアクションメソッドでは同期呼び出しに見えるものをやりたいしかし:
var mailChimpResult =
_PlatformMailChimpService.AddOrUpdateEmailAddressToList(
new OzCpAddOrUpdateEmailAddressToListInput
{
EmailAddress = aFormCollection["aEmailAddress"],
Listid = ApplicationSettings.Newsletter.MailChimpListId.Value,
MailChimpApiKey = ApplicationSettings.Newsletter.MailChimpApiKey.Value
});
if (mailChimpResult.Result == true)
{
//So something
}
「async」を実行する必要があります。 「隠蔽」すると常に痛い発見につながります。通常はデッドロックです(http://stackoverflow.com/questions/13140523/await-vs-task-wait-deadlock)。本質的にその周りには道がありません。 –
@AlexeiLevenkovしかし、私のサービスコールは非同期ハンドルなどを返さないので、どのように実装すればよいでしょうか。あなたは私のコードに基づいて私に例を与えることができますか? – TheEdge
サービスコール中に隠しています。それをポーリングするのではなく、 'AddOrUpdateAsync'の呼び出しを待つ必要があります。これは大きなコードの匂いです。次に、サービスメソッドを非同期にして、コントローラ内で待っています。 – Rhumborl