ボタンをクリックすると、何らかの理由で新しいフォームを開始し、同時にGoogleドキュメントで新しいドキュメントを作成する必要があるアプリを作成しています。上記を正常に実装しましたが、アプリがGoogleドキュメントで新しいドキュメントを作成するのに忙しい間、新しくロードされたフォームのUIがフリーズします。マルチスレッドを使用すると、これを回避できることをどこかで読みました。そこで、2 つのスレッドを作成し、そのうちの 1 つに新しいフォームを作成するためのコードを配置し、もう 1 つのスレッドに Google ドキュメントでドキュメントを作成するためのコードを配置する必要があるかどうかを尋ねたいと思います。または、コードを配置して新しいGoogleドキュメントを作成し、新しいフォーム作成コードをメインプロセスに配置する必要があるスレッドで作成する必要がありますか?? また、既に記述されたコードでスレッド化を実装する最も簡単な方法は何ですか?? 可能であれば、参考文献をいくつか提供してください。
5 に答える
実際には多くのオプションがあります。
(1)バックグラウンドワーカー。WinForms での非同期作業のための最も簡単なプログラミング モデルが本当に必要な場合は、これになります。ただし、一般的には非同期タスクを実行して進行状況を報告するために使用されますが、必要がなければ進行状況を報告する必要はありません。
(2)イベント ベースの非同期パターン。何らかの非同期タスクを実行する本格的なコンポーネントを作成し、進行状況の報告と独自のカスタム イベントを完全に制御したい場合は、これが 1 つの方法です。これは、BackgroundWorker よりもスレッド化を理解するのにも役立ちます。私は視覚的な人間なので、WinForms でこれを行う方法についての完全なビデオ プレゼンテーションを作成しました。
(3)タスク並列ライブラリ。TPL は WinForms で使用できます。その方法については、非常に詳細なブログ投稿をここに書きました。
(4) Async と Await。これには、.NET 4.5、C# 5.0、および Visual Studio 11 (現時点ではベータ版のみ) にのみ含まれる C# 5.0 コンパイラが必要であることに注意してください。ただし、これを行う方法に関する完全なブログ投稿もあります。
(5)スレッドによる ISynchronizedInvoke。これは別のオプションで、これについては完全なブログもあります。
どの方法を選択するかは本当にあなた次第です。私の提案は、それぞれを簡単に見て、対象がどれだけ進んでいるかに基づいて方法を選択すること、またはどの方法があなたの要件を最もよく満たすかを選択することです.
求めていることを実行するために多くの手法を使用できますが、これには Task Parallel Library (TPL) (または ) をお勧めしBackgroundWorker
ます。
新しいフォームの作成/起動にはオーバーヘッドがほとんどないため (ほとんどの場合)、UI スレッドでフォームを起動し、バックグラウンド スレッドで Google ドキュメントを作成する必要があると思います。したがって、TPLを使用すると、次のようになります(非常に基本的な例)
// In click event.
MyForm newForm = new MyForm();
newForm.Show();
Task googleDocTask = Task.Factory.StartNew(() =>
{
// Do your stuff with Google Docs.
// Note you cannot access the UI thread from within this delegate.
});
C# でのスレッド化に関する詳しい説明については、Joseph Albahari のスレッド化に関するページを参照してください。
TPL の詳細とかなり完全な紹介については、こちらを参照してください。
これが役立つことを願っています。
単一のスレッドを作成するだけです。BackgroundWorker を使用することをお勧めします。彼らはかなり率直です。
これをクラスの一番上に投げます:
private BackgroundWorker googleDocWorker = new BackgroundWorker();
これをコンストラクターに入れます:
googleDocWorker.DoWork += new DoWorkEventHandler(googleDocWorker_DoWork);
googleDocWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(googleDocWorker_RunWorkerCompleted);
これらのメソッドをクラスに入れます。
void googleDocWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// You can use this to alert you that the google doc is created.
}
void googleDocWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Create google doc here.
}
これを呼び出して、Google ドキュメントの作成を開始します。
googleDocWorker.RunWorkerAsync();
ここで、何らかのデータを BackgroundWorker に渡す必要がある場合は、本当に必要なものを渡すことができます。オブジェクト配列を使用して、文字列を渡すことも、異なる型の複数のオブジェクトを渡すこともできます。複数のオブジェクトを送信する例を次に示します。
googleDocWorker.RunWorkerAsync(new object[] { "doc name", contents });
つまり、_DoWork メソッドで処理する必要があります。
void googleDocWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Create google doc here.
object[] args = (object[])e.Argument;
String docName = (string)args[0];
SomeClass contents = (SomeClass)args[1];
}
たとえば、ドキュメントを作成した後、作成したばかりのドキュメントに URL を送り返したい場合は、その URL を _DoWork メソッドから _RunWorkerCompleted メソッドに渡すだけです。
void googleDocWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Create google doc here.
...
e.Result = myURL;
}
RunWorkerCompleted メソッドで URL を取得すると、DoWork メソッドとほとんど同じです。
void googleDocWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// You can use this to alert you that the google doc is created.
String docURL = (String)e.Result;
}
それが役立つことを願っています! (:
最も簡単な方法は、BackgroundWorker を使用するか、ThreadPool を使用することです。メイン UI が他のタスクの完了を気にしない場合、スレッドプールはよりシンプルになります。
私見では。Google ドキュメントを作成するスレッドは 1 つだけ作成する必要があります (したがって、2 つのスレッドが作成されます)。