gpt4 book ai didi

c# - 带定时器的观察者模式

转载 作者:行者123 更新时间:2023-11-30 18:05:22 28 4
gpt4 key购买 nike

我在我的应用程序中使用了观察者模式。

我有一个主题,其中有一个名为 'tmr'System.Timers.Timer 对象。此计时器的滴答事件每 60 秒 触发一次。在这个滴答事件中,我将通知所有附属于我的主题的观察者。我使用 for 循环遍历我的观察者列表,然后触发观察者更新方法。

假设我有 10 位观察员关注我的主题。

每个观察者需要 10 秒来完成其处理。

现在,在 for 循环中完成通知会导致在 90 秒后调用最后一个观察者的 Update 方法。即,下一个观察者更新方法仅在前一个观察者完成处理后调用。

但这不是我在申请中想要的。我需要我所有的观察者 Update 方法在计时器滴答发生时立即被触发。这样就没有观察者需要等待。我希望这可以通过线程来完成。

所以,我修改了代码,

// Fires the updates instantly
public void Notify()
{
foreach (Observer o in _observers)
{
Threading.Thread oThread = new Threading.Thread(o.Update);
oThread.Name = o.GetType().Name;
oThread.Start();
}
}

但是我心里有两个疑惑,

  1. 如果有 10 个观察者我的计时器间隔是 60 秒然后语句 new Thread() 将触发 600 次。

    在每个计时器滴答时创建新线程是否有效且值得推荐?

  2. 如果我的观察者花费太多时间来完成他们的更新逻辑,即超过 60 秒怎么办?意味着计时器滴答发生在观察者更新之前。我该如何控制它?

我可以发布示例代码..如果需要...

我使用的代码..

using System;
using System.Collections.Generic;
using System.Timers;
using System.Text;
using Threading = System.Threading;
using System.ComponentModel;

namespace singletimers
{
class Program
{


static void Main(string[] args)
{
DataPullerSubject.Instance.Attach(Observer1.Instance);
DataPullerSubject.Instance.Attach(Observer2.Instance);
Console.ReadKey();
}
}

public sealed class DataPullerSubject
{
private static volatile DataPullerSubject instance;
private static object syncRoot = new Object();
public static DataPullerSubject Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new DataPullerSubject();
}
}

return instance;
}
}

int interval = 10 * 1000;
Timer tmr;
private List<Observer> _observers = new List<Observer>();

DataPullerSubject()
{
tmr = new Timer();
tmr.Interval = 1; // first time to call instantly
tmr.Elapsed += new ElapsedEventHandler(tmr_Elapsed);
tmr.Start();
}

public void Attach(Observer observer)
{
_observers.Add(observer);
}

public void Detach(Observer observer)
{
_observers.Remove(observer);
}

// Fires the updates instantly
public void Notify()
{
foreach (Observer o in _observers)
{
Threading.Thread oThread = new Threading.Thread(o.Update);
oThread.Name = o.GetType().Name;
oThread.Start();
}
}

private void tmr_Elapsed(object source, ElapsedEventArgs e)
{
tmr.Interval = interval;
tmr.Stop(); // stop the timer until all notification triggered
this.Notify();
tmr.Start();//start again
}
}


public abstract class Observer
{
string data;
public abstract void Update();
public virtual void GetDataFromDBAndSetToDataSet(string param)
{
Console.WriteLine("Processing for: " + param);
data = param + new Random().Next(1, 2000);
Threading.Thread.Sleep(10 * 1000);//long work
Console.WriteLine("Data set for: " + param);
}
}


public sealed class Observer1 : Observer
{
private static volatile Observer1 instance;
private static object syncRoot = new Object();
public static Observer1 Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Observer1();
}
}

return instance;
}
}
Observer1()
{
}
public override void Update()
{
base.GetDataFromDBAndSetToDataSet("Observer1");
}

}

public sealed class Observer2 : Observer
{
private static volatile Observer2 instance;
private static object syncRoot = new Object();
public static Observer2 Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Observer2();
}
}

return instance;
}
}
Observer2()
{
}
public override void Update()
{
base.GetDataFromDBAndSetToDataSet("Observer2");
}

}
}

谢谢和亲切的问候。

最佳答案

  • 使用 new Thread气馁。使用 TaskTask<T>
  • 您创建 Observable 模式框架的最佳尝试可能只会接近 Rx .使用解决您提到的问题的方法(即如果处理花费太多时间)。 Rx 将为您提供巨大的灵 active 来定义您的可观察场景。

关于c# - 带定时器的观察者模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5648166/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com