3

私はトラフィック監視にPcap.Netを使用します。ユーザーがキャンセルを要求するまでパケットを受信する必要があります。私はタスクこの方法(簡体字)の監視を作成:終わりのないライブラリメソッドを含む打ち切りタスク(キャンセル要求をチェックする機能はありません)

var task1 = Task.Run(() => { communicator.ReceivePackets(0, PacketHandlerCallback); } /*, token*/); 

ここ0ことPacketHandlerCallbackは、それぞれのパケットを受信するために実行される方法であり、ReceivePacketsの実行が終了したことがないと言います。 ReceivePacketsは同期であり、キャンセルをサポートしていません。私の質問では一般的には、私たちが編集することができない他の無限の同期方法である可能性があります

このメソッドの実行を停止する方法はありますか?

  • ちょうどキャンセルが要求された場合、我々はまた、明示的に、電子をチェックする必要がありますので、助けにはならないタスクにキャンセルトークンを渡します。 g。 token.throwIfCancellationRequested()に電話してください。

  • トークンをコールバックメソッドに渡すことは、新しいパケットを受け取るまで呼び出されないため、このメソッドは呼び出されませんが、キャンセル後すぐにタスクを停止したいと考えています。

  • BackgroundWorkerを使用すると、CancellationPendingにチェックする必要があるため、同じ質問が表示されます。定期的に取り消し要求をチェックし、ReceivePacketsはまだを実行されるので、その後var task = Task.WhenAny(task1, task2)を書いても解決しないtask2を作成

Thread.Abort()を使用する必要がありますか他の優雅な解決方法がありますか?
TPLについても同様の質問がありますが、私は単純で有益な答えは見つかりません。

+0

:ドキュメントのコードから

コードがハングアップしてしまう心配はありません。すべてをクリーンアップしたいときは、コミュニケータを処分できます。 –

+0

@Scott素晴らしい提案、ありがとうございます。私はそれが何について質問されていないことを知っているが、それは私が今必要なものです。あなたは 'while(true){communicator.ReceiveSomePackets(/ * args * /);}を書くとそれを確認してください。 token.throwIfCancellationRequested(); } 'ノンブロッキングコミュニケータの場合キャンセル要求チェック中に受信できるパケットは失われませんか? –

+0

前にライブラリを使用したことはありません。私はソースをチェックして、プロパティとそのプロパティでメモを見ました。 –

答えて

1

通常、実際にはThread.Abortは、古くて危険な方法として使用しないでください。しかし、あなたの状況は無限の方法を止めるためにスレッド/プロセスをkillする必要があるように見えます。

スレッドの中断を避けることをお勧めします。中断されたスレッドはリソースを正しくクリーンアップできないため、システムが不安定になる可能性があります。あなたはrun your method in new AppDomainかもしれませんし、キャンセル要求の場合はそのドメインをアンロードしてください。また、Scottが述べたように、別のProcessも解決策です。

何らかの理由でこれがオプションではない場合は、subscribe for cancellation of your token with Thread.CurrentThread.Abortとすることができますが、もし私があなただったら、私はできる限りこのオプションを避けます。

また、task from cancellation tokenを作成し、非同期にキャンセルを待つためにWhenAllを使用することもできます。

1

Thread.Abortよりもはるかに優れたソリューションをキャンセルできない状況では、キャンセルできないコードを別のプロセスに置くことができます。

これは、OSがプロセスの終了時にハンドルなどの保持されていないOSリソースを解放するため、スレッドが保持するすべてのリソースの保証されたリリースを提供します。スレッドを中止した場合や、別のAppDomainをシ​​ャットダウンします。

2番目のプロセスが書かれているときは、WCF over named pipesのようなものを使うことができるので、プロセス内の他の通常の機能と同様に外部プロセスとやり取りできます。

1

PacketCommunicator.Break()の方法があります。あなたは `communicator.NonBlocking = true`に設定すると、代わりに非ブロッキングモードで` communicator.ReceiveSomePackets`を使用するようにコードを書き換える検討する必要があります

/// <summary> 
/// Set a flag that will force ReceiveSomePackets(), ReceivePackets() or ReceiveStatistics() to return rather than looping. 
/// They will return the number of packets/statistics that have been processed so far, with return value BreakLoop. 
/// <seealso cref="ReceiveSomePackets"/> 
/// <seealso cref="ReceivePackets"/> 
/// <seealso cref="ReceiveStatistics(int, HandleStatistics)"/> 
/// </summary> 
/// <remarks> 
/// <list type="bullet"> 
///  <item>This routine is safe to use inside a signal handler on UNIX or a console control handler on Windows, as it merely sets a flag that is checked within the loop.</item> 
///  <item>The flag is checked in loops reading packets from the OS - a signal by itself will not necessarily terminate those loops - as well as in loops processing a set of packets/statistics returned by the OS.</item> 
///  <item>Note that if you are catching signals on UNIX systems that support restarting system calls after a signal, and calling Break() in the signal handler, you must specify, when catching those signals, that system calls should NOT be restarted by that signal. Otherwise, if the signal interrupted a call reading packets in a live capture, when your signal handler returns after calling Break(), the call will be restarted, and the loop will not terminate until more packets arrive and the call completes.</item> 
///  <item>ReceivePacket() will, on some platforms, loop reading packets from the OS; that loop will not necessarily be terminated by a signal, so Break() should be used to terminate packet processing even if ReceivePacket() is being used.</item> 
///  <item>Break() does not guarantee that no further packets/statistics will be processed by ReceiveSomePackets(), ReceivePackets() or ReceiveStatistics() after it is called; at most one more packet might be processed.</item> 
///  <item>If BreakLoop is returned from ReceiveSomePackets(), ReceivePackets() or ReceiveStatistics(), the flag is cleared, so a subsequent call will resume reading packets. If a different return value is returned, the flag is not cleared, so a subsequent call will return BreakLoop and clear the flag.</item> 
/// </list> 
/// </remarks> 
関連する問題