我有一个C#程序需要每隔X分钟调度一个线程,但前提是先前调度的线程(从X分钟开始)以前还没有运行.
Timer单独一个普通的老人将无法工作(因为无论是否先前已发送的流程已完成,它每X分钟发送一次事件).
将要发送的进程在执行任务所花费的时间内变化很大 - 有时可能需要一秒钟,有时可能需要几个小时.如果它从上次启动时仍在处理,我不想再次启动该过程.
谁能提供一些有用的C#示例代码?
Grx*_*x70 55
在我看来,在这种情况下的方法是使用System.ComponentModel.BackgroundWorker类,然后IsBusy每次要分派(或不)新线程时,只需检查其属性.代码非常简单; 这是一个例子:
class MyClass
{
private BackgroundWorker worker;
public MyClass()
{
worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
Timer timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!worker.IsBusy)
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
//whatever You want the background thread to do...
}
}
Run Code Online (Sandbox Code Playgroud)
在我使用的这个例子中System.Timers.Timer,但我相信它也应该与其他计时器一起使用.该BackgroundWorker班还支持进度报告和取消,并采用与调度线程通信的事件驱动模型,所以你不必担心volatile变量和...
编辑
这里有更详细的例子,包括取消和进度报告:
class MyClass
{
private BackgroundWorker worker;
public MyClass()
{
worker = new BackgroundWorker()
{
WorkerSupportsCancellation = true,
WorkerReportsProgress = true
};
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
Timer timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!worker.IsBusy)
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker w = (BackgroundWorker)sender;
while(/*condition*/)
{
//check if cancellation was requested
if(w.CancellationPending)
{
//take any necessary action upon cancelling (rollback, etc.)
//notify the RunWorkerCompleted event handler
//that the operation was cancelled
e.Cancel = true;
return;
}
//report progress; this method has an overload which can also take
//custom object (usually representing state) as an argument
w.ReportProgress(/*percentage*/);
//do whatever You want the background thread to do...
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//display the progress using e.ProgressPercentage and/or e.UserState
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled)
{
//do something
}
else
{
//do something else
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,为了取消进一步执行,只需调用即可worker.CancelAsync().请注意,这是完全由用户处理的取消机制(它不支持线程中止或任何类似的开箱即用).
Mat*_*int 22
你可以维持一个挥发性的bool来实现你的要求:
private volatile bool _executing;
private void TimerElapsed(object state)
{
if (_executing)
return;
_executing = true;
try
{
// do the real work here
}
catch (Exception e)
{
// handle your error
}
finally
{
_executing = false;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在已过去的回调中禁用和启用计时器.
public void TimerElapsed(object sender, EventArgs e)
{
_timer.Stop();
//Do Work
_timer.Start();
}
Run Code Online (Sandbox Code Playgroud)
你可以只使用System.Threading.Timer,只是设置Timeout到Infinite你处理你的数据/方法之前,那么当它完成重启Timer准备下一次呼叫.
private System.Threading.Timer _timerThread;
private int _period = 2000;
public MainWindow()
{
InitializeComponent();
_timerThread = new System.Threading.Timer((o) =>
{
// Stop the timer;
_timerThread.Change(-1, -1);
// Process your data
ProcessData();
// start timer again (BeginTime, Interval)
_timerThread.Change(_period, _period);
}, null, 0, _period);
}
private void ProcessData()
{
// do stuff;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54950 次 |
| 最近记录: |