2016-08-16 5 views
-2

私はList<System.Security.Claim>のリストを持っており、各請求を非同期で追加したいと考えています。すべてのタスクを実行し、後ですべてのタスクが実行されたことを確認するためにbooleanを設定する方法が不思議です。また、私はこれを試してみましたタスクのリストを実行するには?

foreach (var claim in claims) 
{ 
    claimTasks.Add(UserManager.AddClaimAsync(user.Id, claim)); 
} 

claimResultSucceeded = Task.WhenAll(claimTasks).IsCompleted; 

foreach (var claim in claims) 
{ 
    claimTasks.Add(Task.Run(() => UserManager.AddClaimAsync(user.Id, claim))); 
} 

claimResultSucceeded = Task.WhenAll(claimTasks).IsCompleted; 

編集:あなたは下の写真で見ることができるように、タスクがフォルト状態をヒットしている:

{ "前の の非同期操作が完了する前にこのコンテキストで2番目の操作が開始されました 操作が完了しました 'await'を使用して、非同期操作が確実に行われるようにします が完了してから、このコンテキストで別のメソッドを呼び出します。 メンバーは、スレッドセーフであるとは限りません。「任意のインスタンス}

enter image description here

+1

'.IsCompleted'に何を期待しますか?あなたのコードが何を期待しているのか、あなたが何をしているのかを述べてください。 –

+0

@ LasseV.Karlsen .IsCompletedは、すべてのタスクが実行された後に、真または偽の結果を含む必要があります。私は詳細をつけて質問を更新しました。 – user1477388

+1

@ user1477388いいえ、タスクが現在完了しているかどうかを返し、直ちにそれを返します。 – Servy

答えて

1

あなたはよろしいですか?Task.WhenAllタスクのセットを取る(ので、それらのタスクから任意の戻り値を受け入れる)し、

私は次のコードサンプルをまとめました。これは基本的にあなたが示していたものです(ナンセンスデータを使って確認しています)コンパイルには十分でした) -

static async void Main(string[] args) 
{ 
    // Declare some references to work with (this data is rubbish, it's just here so 
    // that everything compiles) 
    var userManager = new UserManager<User, Key>(null); 
    var user = new User(); 
    var claims = new List<Claim>(); 
    var claimTasks = new List<Task<IdentityResult>>(); 

    // This is basically the code that appears in the question - it compiles fine 
    foreach (var claim in claims) 
    { 
     claimTasks.Add(userManager.AddClaimAsync(user.Id, claim)); 
    } 

    // WhenAll returns a single task that will be completed when all of the individual 
    // claims tasks have completed 
    var claimResults = await Task.WhenAll(claimTasks); 

    // When this happens, you should be able to look at each of the IdentityResults 
    // instances in the claimResults array to ensure they all succeeded 
    // Note: I'm presuming a little here since I'm not too familiar with these types, but 
    // it seems reasonable that the Succeeded flag on each IdentityResult should indicate 
    // whether or not it was successfully retrieved 
    var allRequestsSucceeded = claimResults.All(c => c.Succeeded); 
} 

// This struct and class have no purpose other than making the code compile 
public struct Key : IEquatable<Key> 
{ 
    public bool Equals(Key other) { throw new NotImplementedException(); } 
} 

public class User : IUser<Key> 
{ 
    public Key Id 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public string UserName 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 
} 
+0

追加した写真のとおり、コードがコンパイルされて実行されます。ただし、タスクは決して実行されません。エラーが発生しているため、エラー状態になります(これは以前は認識していませんでした)。 – user1477388

+0

ああ、そうです。あなたの質問は元々、あなたが持っていた戻り値型の問題であると言っていました - あなたがブールを求めていたIdentityResultなので、コードはコンパイルされなかったと推測しました。 @Lasse Vのコメントを考慮して、私の答えを(未来の子孫のために)微調整するつもりです。私が気づいていなかったとは信じられませんが、 "IsCompleted"はチェックするのが間違っていて、WhenAllによって返されたTaskが待たれるべきです。それが完了すると、すべての子タスクが完了した(成功したかどうかは別の問題かもしれません)。 –

1

新しいエラーはEntity Frameworkから発生しています。 dbコンテキストインスタンスごとに1つの非同期操作しか持てません。

foreach (var claim in claims) 
{ 
    var result = await UserManager.AddClaimAsync(user.Id, claim); 
    if (result.Succeded == false) { 
     // Handle the error 
    } 
} 

EDIT: 組み込ま@Dan Robertsアドバイスだけでこれを行います。

+0

これで、すべてのタスクが正常に完了したことを確認する方法はありますか? – user1477388

+1

これを "var addClaimResult = await UserManager.AddClaimAsync(user.Id、claim);"に変更すると、ループ内で "addClaimResult.Succeeded"の各呼び出しをチェックし、いずれかが成功しなかったと言う場合はフラグを設定することができます。この方法では、並列処理は行われませんが、各AddClaimAsync呼び出しが処理されている間にスレッドが結ばれないという点で非同期になります。これは重要です。私はマイクがおそらくこれらのアイデンティティークラスを私よりもはるかによく知っていると思います。この答えは私のものよりも良いかもしれません(私には賞賛されています)。 –

+0

良いキャッチ@ダンロベルツ、私は結果を確認するために編集しました。 –

関連する問題