从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可能已经有了这个,因此出现了这个问题。

从Timer向原始线程传递数据

您会考虑使用分派器吗?(虽然你也需要调用一些方法)

当某个线程(可能不是主线程)创建您提到的计时器时,您也可以使用同一线程创建调度程序。之后,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