これは間違いなく疑問に思うかもしれませんが、これはすでに別の場所で回答されている場合は、検索が表示されないので、何か決定的。一言で言えばThread.JoinもUIスレッドで子スレッドをブロックしています
、私の問題は、私はchildThreadを停止するようにフラグが付けられている子スレッドのUIスレッドでchildThread.Join()を行うときにブロックするように思えるだけでなく、すべてのでメインスレッドということですちょうどハングアップします。
Joinを使用したためにUIがブロックされることは、とにかく終了するように指示された後、childThreadが1秒以内に終了する必要があるため、それ自体は問題ではありません。
これは、何らかの情報を返すが他のプロセスと同時に実行できない別のメソッドを実行する前に、繰り返しプロセスを実行しているスレッドが終了するのを待っている間に発生します。
私のWinformsアプリケーションは、ハードウェア用のC APIをピンボーキングすることによって、USBハードウェアと統合しています。
ハードウェアAPIには、無期限に繰り返し実行されるプロセスを開始するメソッドがあり、新しい情報を迅速にコールバックしてUIに渡す必要があります。
この操作は、ハードウェアAPIの別の呼び出しによって取り消すことができます。この呼び出しは、ハードウェアが認識できるようにフラグを設定して終了することができます。
私はこのC APIを独自のC#コードでラップしています。ラッパー内では、アクティビティがUIをブロックしないように、別のスレッドで開始プロセス呼び出しを開始する必要がありました。
ここには、私がやっていることの大まかな編集ハイライトがあります。私はchildThread.Join()アプリケーション全体が(私はUIのために期待する、それは大丈夫です)停止して磨くとchildThreadもコールバックが取得することはありませんので、止めるように思わ呼び出し、このコードを使用して
public class DeviceWrapper
{
Thread childThread = null;
void DeviceWrapper
{
//Set the callback to be used by the StartGettingInformation() process
PInvokeMethods.SetGetInformationCallback(InformationAcquiredCallback);
}
public void StartProcess()
{
childThread = new Thread(new ThreadStart(GetInformationProcess))
childThread.Start();
}
void GetInformationProcess()
{
PInvokeMethods.StartGettingInformation();
}
//This callback occurs inside the childThread
void InformationAcquiredCallback(Status status, IntPtr information)
{
//This callback is triggered when anything happens in the
//StartGettingInformation() method, such as when the information
//is ready to be retrieved, or when the process has been cancelled.
if(status == Status.InformationAcquired)
{
FireUpdateUIEvent();
}
//If the cancel flag has been set to true this will be hit.
else if(status == Status.Cancelled)
{
//Reset the cancel flag so the next operation works ok
PInvokeMethods.SetCancelFlag(false);
childThread.Abort();
}
}
//This method runs once, and can't run at the same time as GetInformationProcess
public string GetSpecificInformation()
{
//This triggers InformationAcquiredCallback with a status of Cancelled
StopProcess();
if(childThread.IsAlive)
{
childThread.Join();
}
return PInvokeMethods.GetSpecificInformation();
}
public void StopProcess()
{
PInvokeMethods.SetCancelFlag(true);
}
}
もう一度ヒットします。
私が代わりに次のコードを使用する場合は、:
public string GetSpecificInformation()
{
//This triggers InformationAcquiredCallback with a status of Cancelled
StopProcess();
string s = "";
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
if(childThread.IsAlive)
{
childThread.Join();
}
s = PInvokeMethods.GetSpecificInformation();
}));
return s;
}
そして、すべてが期待通りにヒット取得し、childThreadが完了しないと明らかに私の文字列がWaitCallback火災の前に空の返却とに割り当てます以外のすべてが、うまくありますそれ。
私はQueueUserWorkItemとWaitCallbackを使用してイベントを発生させて文字列を返すように、それを吸い取ってクラスを変更するだけですか?
childThreadもブロックする原因になっています。
または、私が使用しているはずの別の戦術またはクラスがあります。.NET 3.5のことを覚えておいてください。
私は過去30年間、TThread.WaitFor()とデッドロックを生成するハードロック同期メカニズムを使用してDelphi開発者を止めようとしました。ちょうど私がどこかに行っていると思うと、JavaとC#の開発者はjoin()を発見します。終わりのない悪夢。 –
私が絶望的で奥行きのない限り、私はこれに触れていないと信じています;)だから代わりに何をお勧めしますか? – Nanhydrin
あなたはエリックと他の人の話を聞いてください。 Invoke、BeginInvokeなどは間違っていません。イベントハンドラで待機しないでください - 他のスレッドが何か言いたいことがあるときに、デリゲートがメインスレッドで起動されることによって返されるシグナルに作用してください。 –