2016-06-16 18 views
0

私はREST APIに接続し、さまざまなオブジェクトを取得するためにいくつかのエンドポイントを呼び出しています。私は、REST APIを呼び出し、結果を得るためにGetAll()を呼び出して、各RestService<T>について一連のメソッドを並列に実行する

RestService<Agent> agentService = new RestService<Agent>(auth, new AgentApi()); 
RestService<Ticket> ticketService = new RestService<Ticket>(auth, new TicketApi()); 
RestService<Company> companyService = new RestService<Company>(auth, new CompanyApi()); 
RestService<Contact> contactService = new RestService<Contact>(auth, new ContactApi()); 

GetAll()は数になり舞台裏

RestResult<Agent> agentResults = agentService.GetAll(); 
RestResult<Company> companyResults = companyService.GetAll(); 
RestResult<Contact> contactResults = contactService.GetAll(); 
RestResult<Ticket> ticketResults = ticketService.GetAll(); 

を私がダウンロードしたいタイプごとにRestService<T>を作成しますHttpWebRequestのリクエスチョン。

私は何とか4 GetAll()呼び出しを並列に呼び出すことを考えています。理論的には、複数の要求を1つずつ繰り返してREST APIに渡すことができます。

RestResult<Agent> agentResults; 
RestResult<Company> companyResults; 
RestResult<Contact> contactResults; 
RestResult<Ticket> ticketResults; 

Parallel.Invoke(
    () => agentResults = agentService.GetAll(), 
    () => companyResults = companyService.GetAll(), 
    () => contactResults = contactService.GetAll(), 
    () => ticketResults = ticketService.GetAll() 
); 

しかし、変数が初期化されることはありませんように見えます:私が持っていた

ひとつのアイデアでした。

これにアプローチする方法についてのご意見はありますか?

+0

「それはのように見える」とはどういう意味:

最も簡単な解決策は、単にデフォルト値(null)を使用して手動でそれらをinitalizeするのですか?彼らはまだ 'ヌル'ですか?もしそうなら、 'GetAll()'メソッドが何か他のものを返したことを確かめますか? –

+0

申し訳ありませんが、私が意味したのは、コンパイルエラーが発生し、後でそれらを試して使用するときに、変数が割り当てられていないということです。 – moose56

答えて

2

あなたのコンパイラは、コンパイラがセマンティクスParallel.Invoke()を理解していないので、変数が初期化されていないことを警告します。

コンパイラが知っている唯一のことは、その関数にいくつかのラムダを渡すことです。しかし、彼らはいつ実行されるのかを推測することはできません。コンパイラはParallel.Invoke()がすべてActionが完了したときにのみ戻ることを知らない。特にラムダが変数を初期化していることはわかりません。

したがって、Parallel.Invoke()の後であっても、変数にはまだ値が割り当てられていません。

RestResult<Agent> agentResults = null; 
RestResult<Company> companyResults = null; 
RestResult<Contact> contactResults = null; 
RestResult<Ticket> ticketResults = null; 

Parallel.Invoke(
    () => agentResults = agentService.GetAll(Epoch), 
    () => companyResults = companyService.GetAll(Epoch), 
    () => contactResults = contactService.GetAll(Epoch), 
    () => ticketResults = ticketService.GetAll(Epoch) 
); 
+0

ありがとう、私は何かが欠けていたかどうかは分かりませんでした。 – moose56

1

この質問を見ると、同じ問題があるようです。 Parallel.Invokeは非同期操作を待っていないようです。代わりに、すべてのタスクが完了するのを待つためにTask.WhenAllを使用します。 Parallel.Invoke does not wait for async methods to complete

RestResult<Agent> agentResults; 
RestResult<Company> companyResults; 
RestResult<Contact> contactResults; 
RestResult<Ticket> ticketResults; 

var t1 = Task.Run(() => agentResults = agentService.GetAll(Epoch)) 
var t2 = Task.Run(() => companyResults = companyService.GetAll(Epoch)); 
var t3 = Task.Run(() => contactResults = contactService.GetAll(Epoch)); 
var t4 = Taks.Run(() => ticketResults = ticketService.GetAll(Epoch)); 

await Task.WhenAll(t1,t2,t3,t4); 
//results should be filled here 
+0

それが理由だとは思わない、ラムダOPが 'Parallel.Invoke()'に渡しているのは、非同期ではありません。 'GetAll'が' Task'を返しても、これは変数に代入されるべきです。また、 'Parallel.Invoke'はすべての' Action'が完了した場合にのみ返されます。 –

+0

ありがとう、しかし私はコンパイルエラーを取得しようとすると、変数が割り当てられていないと言って、後で待ってから使用します。 – moose56

+0

あなたのコードをスニペットに変換する私の頭の上からちょうどすぐに申し訳ありません、あなたは自分の例で行ったように 'null'でそれらを割り当てることができました。おそらくラムダ式で結果を返し、タスクの結果をキャプチャする方が良いでしょう。しかし、Renéが指摘しているように、私はあなたの操作を非同期と仮定し、これが問題を引き起こしていました。 –

関連する問題