私は、作業項目の集合で構成されるジョブオブジェクトを持っています。各ジョブには、それ自体がWatcherClass
に関連付けられており、データベースを頻繁にチェックして実行をキャンセルする必要があるかどうかを確認します。ワークフローのどの繰り返しでもキャンセルすることができます。キャンセルされた場合、foreach
ブロックから実行されているスレッドはキャンセルを正常に終了して終了します。同じロックでロック内のオブジェクトを変更する
ウォッチャーコードにデッドロックが発生することがありますか? Timer.Change(Timeout.Infinite、Timeout.Infinite)を使用して、1つのスレッドのみをタイマーコールバックで処理できるようにしようとしていますが、私は変更しています。WatcherClass.Job
ロックステートメント内では、同じロックオブジェクト内の_Jobのget/setは同じですか?)コードは正常に動作しているように見えますが、実際に何も表示されていないことがわかります。
using (WatcherClass watcher = new WatcherClass())
{
watcher.CancelTokenSource = new CancellationTokenSource();
watcher.Start();
foreach (SomeJob job in worksflow.Jobs)
{
watcher.Job = job;
//Do some stuff async
//Do some more stuff async
}
}
public class WatcherClass : IDisposable
{
private System.Threading.Timer _WatcherTimer;
private readonly object locker = new object();
private bool _Disposed = false;
private SomeJob _Job;
public SomeJob Job
{
get
{
lock (locker)
{
return _Job;
}
}
set
{
lock (locker)
{
_Job= value;
}
}
}
public System.Threading.Task.CancellationTokenSource
CancelToken { get; set; }
public WatcherClass()
{
_WatcherTimer = new Timer(new TimerCallback(DoCheck), null,
Timeout.Infinite, Timeout.Infinite);
}
public void Start()
{
_WatcherTimer.Change(30000, Timeout.Infinite);
}
public void DoCheck(object state)
{
lock (locker)
{
if (_Disposed || this.CancelToken.IsCancellationRequested)
return;
_WatcherTimer.Change(Timeout.Infinite, Timeout.Infinite);
//Check database to see if task is cancelled
if (cancelled)
{
this.CancelToken.Cancel();
_Job.CancelResult = CancelResult.CanceledByUser;
_Job.SomeOtherProperty = true;
}
else
{
//Safe to continue
_WatcherTimer.Change(30000, Timeout.Infinite);
}
}
}
public void Dispose(bool disposing)
{
lock (locker)
{
if (disposing)
{
if (_WatcherTimer != null)
_WatcherTimer.Dispose();
}
_Disposed = true;
}
}
}
これはあなたの 'class task'、' class CancelToken'であり、TPLからのものではありませんか? –
@Henk:CancelTokenはTPLのもので、タスクはそうではありません。タスクは私がこの例で呼び出すものです。ありがとう –
混乱を避けるためにJob(質問)に置き換えてください。特にCancelTokenを使用した場合 –