从Timer向原始线程传递数据
本文关键字:数据 线程 原始 Timer | 更新日期: 2023-09-27 18:05:27
这个问题可能是如何在c#控制台应用程序中添加计时器和其他一些类似问题的副本,但找不到我正在寻找的答案,所以再问一遍。
问题:如何将数据从定时器(System.Timers.Timer
)的Elapsed
事件传递到创建定时器的线程(该线程可能不是Main
线程,而是由Main
生成的另一个线程)?
我想可能有一些简单的方法来实现这个目标。比如在创建工作线程的线程中调用BackgroundWorker
ProgressChanged
事件,但在MSDN文档或SO中找不到方法。我见过的大多数例子都在计时器线程(https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx)中执行一些操作,但不向原始线程传递任何内容。不用说,我对c#/还是个新手。所以一个解决方案+引用指针是值得赞赏的。
编辑:我宁愿不使用Invoke()
/InvokeRequired
模式(参见如何使用定时器的安全线程(从不同的线程改变定时器属性)),因为这不是一个表单应用程序。我很想通过创建一个BackgroundWorker
来解决这个问题,它每隔一段时间就向原始线程报告(DoWork
将只是循环中的sleep()
),但我认为。net可能已经有了这个,因此出现了这个问题。
您会考虑使用分派器吗?(虽然你也需要调用一些方法)
当某个线程(可能不是主线程)创建您提到的计时器时,您也可以使用同一线程创建调度程序。之后,dispatcher.invoke()将让原始线程为您执行这些任务。
在我看来,一个简单的锁定机制是你所需要的:
private Object _sync = new Object();
void MyTimerFinished()
{
lock (_sync)
{
// Access shared data
...
}
}
void CodeExecutingInMainThread()
{
lock (_sync)
{
// Access shared data
...
}
}
好的,所以这就是我想到的(lock
s和Queue
s的解决方案听起来有点太复杂对我来说-可能更简单,但还没有尝试过)
public class ReportingTimer
{
public event EventHandler Elapsed;
private int _interval;
private BackgroundWorker _worker;
public ReportingTimer(int interval)
{
_interval = interval;
_worker = new BackgroundWorker();
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += _worker_DoWork;
_worker.ProgressChanged += _worker_ProgressChanged;
}
public void Start()
{
if (!_worker.IsBusy)
{
_worker.RunWorkerAsync();
}
}
public void Stop()
{
if (_worker.IsBusy)
{
_worker.CancelAsync();
}
}
private void _worker_DoWork(object sender, DoWorkEventArgs e)
{
while (!_worker.CancellationPending)
{
Thread.Sleep(_interval);
_worker.ReportProgress(1);
}
if (_worker.CancellationPending)
{
e.Cancel = true;
}
}
private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (!_worker.CancellationPending)
{
if (Elapsed != null)
{
Elapsed(this, new EventArgs());
}
}
}
}
请批评。
Edit:这符合我的目的,接口类似于Timer
类,实际上是我想要的股票Timer
。