【问题标题】:Working with threads in windows service [closed]在 Windows 服务中使用线程[关闭]
【发布时间】:2013-07-23 08:46:04
【问题描述】:

问题?我有一个win服务,每分钟执行一个方法,示例代码:

protected override void OnStart(string[] args)
        {

            //Elapsed event
            timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);

            timer.Interval = 60000;

            //enable timer
            timer.Enabled = true;

        }

protected override void OnStop()
        {
            timer.Enabled = false;
        }

 private void OnElapsedTime(object source, ElapsedEventArgs e)
        {

            timer.Enabled = false;

            SEND_DATA_TO_CLIENT();

            timer.Enabled = true;
        }

好的,现在方法 SEND_DATA_TO_CLIENT();是一种从数据库收集数据并将其发送到客户端的方法,我必须有第二种方法 PROCESS_DATA();一种在将数据发送到客户端之前处理数据的方法,但问题是这两种方法同时在数据库中的相同表上工作,所以我不想获得数据库锁定或其他一些数据库错误,并且使用计时器是方法的机会发生冲突,一种方法处理数据,另一种方法将数据发送到客户端,但它们必须同时工作,也必须分开工作,有没有办法用线程做这种事情?

【问题讨论】:

  • 请将超过 7 行的句子改为逐步描述您的代码的功能、您希望它做什么以及您尝试做什么以使其做到这一点。
  • 方法中的代码无关紧要,我要做的是同时运行前面提到的方法,不是用计时器而是用线程,全部
  • 我说的不是你的代码,而是你的问题的解释,有点不清楚,不可读。

标签: c# windows multithreading windows-services


【解决方案1】:

如何摆脱您的问题的一个想法可能是双缓冲线程循环。 这是实现游戏循环的一个很好的概念,但它也可能满足您的需求。

您将有一个线程在无限循环中执行 PROCESS_DATA,而另一个线程在无限循环中执行 SEND_DATA_TO_CLIENT。你有两个缓冲区。这可以是任何类型的类或保存 PROCESS_DATA 方法返回的信息的结构。

SEND_DATA_TO_CLIENT 循环首先被锁定,直到 buffer_1 循环被 PROCESS_DATA 线程填充。然后 PROCESS_DATA 释放 SEND_DATA_TO_CLIENT 上的锁并交换缓冲区。现在 SEND_DATA_TO_CLIENT 拥有已填充的缓冲区并可以随心所欲地处理数据。在此过程中,PROCESS_DATA 同时处理下一个数据并等待 SEND_DATA_TO_CLIENT 完成或解锁 SEND_DATA_TO_CLIENT 以交换缓冲区。

我希望你明白我的意思。如果没有,我可以给你一张照片。

/// <summary>
/// Author: Samuel Egger
/// </summary>
class Program
{
    private static EventWaitHandle swappedWh = new EventWaitHandle(false, EventResetMode.AutoReset);

    private static object lockerA = new object();
    private static object lockerB = new object();

    private static int counter = 0;

    // The queues can be of any type which holds your data e.g. a struct or a class
    private static Queue<string> dataQueueA = new Queue<string>();
    private static Queue<string> dataQueueB = new Queue<string>();

    static void Main(string[] args)
    {
        Thread sendDataToClientThread = new Thread(SendDataToClient);
        Thread processDataThread = new Thread(ProcessData);

        sendDataToClientThread.IsBackground = false;

        processDataThread.Start();
        sendDataToClientThread.Start();
    }

    private static void ProcessData()
    {
        while (true)
        {
            lock (lockerA)
            {
                // Your time consuming process goes here. The result then must
                // must be saved (e.g. state) and then enqueued
                dataQueueA.Enqueue(state);
            }

            // If the operations result is equal to 2, then the render thread is done
            // and is waitung for getting unblocked
            if (Interlocked.Increment(ref counter) == 2)
            {
                counter = 0;
                SwapQueues();
                swappedWh.Set();
            }
            else
            {
                swappedWh.WaitOne();
            }
        }
    }

    private static void SendDataToClient()
    {
        while (true)
        {
            lock (lockerB)
            {
                // Send the data generated by the process data thread
                while (dataQueueB.Count > 0)
                {
                    string data = dataQueueB.Dequeue();
                    // Your process of sending the data goes here
                }
            }

            if (Interlocked.Increment(ref counter) == 2)
            {
                counter = 0;
                SwapQueues();
                swappedWh.Set();
            }
            else
            {
                swappedWh.WaitOne();
            }
        }
    }

    static void SwapQueues()
    {
        // Wait until both threads are "done" before swapping

        lock (lockerA)
        {
            lock (lockerB)
            {
                Queue<string> tmpQueue = dataQueueA;
                dataQueueA = dataQueueB;
                dataQueueB = tmpQueue;
            }
        }
    }
}

我希望这个小技巧能帮到你。

【讨论】:

  • 干得好,山姆,这正是我需要的,你能写一些代码如何做到这一点
  • 如果你愿意,我可以在晚上给你写一些代码。目前我在工作,没有太多时间。
  • 没问题,不急,我有时间,非常感谢Sam!
  • 所以,我已经为您添加了代码示例。请让我知道它是否对您的需求有所帮助。
  • 非常感谢,这是一些不错的工作!!!
猜你喜欢
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
相关资源
最近更新 更多