私は MVP アプリケーション C#、.NET 4、WinForms を持っています。NamedPipe 経由でサードパーティ アプリと通信する Bridge クラスを使用します。コマンド フローは次のようになります。View → Presenter → Manager → Bridge → Client と逆の順序で戻ります。ビューはマルチタスク用に準備されています。その結果で発生するイベントによって Manager でリバース チェーンを分割しましたが、役に立ちません。
// View class
public void AccountInfo_Clicked() { presenter.RequestAccountInfo(); }
public void UpdateAccountInfo(AccountInfo info)
{
if (pnlInfo.InvokeRequired)
pnlInfo.BeginInvoke(new InfoDelegate(UpdateAccountInfo), new object[] {info});
else
pnlInfo.Update(info);
}
// Presenter class
public void RequestAccountInfo() { manager.RequestAccountInfo(); }
private void Manager_AccountInfoUpdated(object sender, AccountInfoEventArgs e)
{
view.UpdateAccountInfo(e.AccountInfo);
}
// Manager class
public void RequestAccountInfo()
{
AccountInfo accountInfo = bridge.GetAccountInfo();
OnAccountInfoUpdated(new AccountInfoEventArgs(accountInfo));
}
// Bridge class
public AccountInfo GetAccountInfo() { return client.GetAccountInfo(); }
// Client class
public AccountInfo GetAccountInfo()
{
string respond = Command("AccountInfo");
return new AccountInfo(respond);
}
private string Command(string command)
{
var pipe = new ClientPipe(pipeName);
pipe.Connect();
return pipe.Command(command);
}
コマンド処理中に UI のフリーズを解除したい。他にも実行できるコマンドがあります。最後に、すべてのコマンドがCommand(string command)
クライアントのメソッドに到達します。
task と ContinueWith を使用してマネージャーでチェーンを切断しようとしましたが、パイプの接続に失敗しました。その理由は、クライアントがスレッド セーフではないためです。
// Manager class
public void RequestAccountInfo()
{
var task = Task<AccountInfo>.Factory.StartNew(() => bridge.GetAccountInfo());
task.ContinueWith(t => { OnAccountInfoUpdated(new AccountInfoEventArgs(t.Result)); });
}
私の質問は次のとおりです。Task、ContinueWith を使用する場所、およびロックする場所はどこですか?
Command(string command)
究極の方法だからこそロックできるのだと思います。
private string Command(string command)
{
lock (pipeLock)
{
var pipe = new ClientPipe(pipeName);
pipe.Connect();
return pipe.Command(command);
}
}
Command
Client クラスで Task、Wait in を使用できますか?