-1

问题?我有一个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(); 一种在将数据发送到客户端之前处理数据的方法,但问题是这两种方法同时在数据库中的相同表上工作,所以我不想获得数据库锁定或其他一些数据库错误,并且使用计时器是方法的机会发生冲突,一种方法处理数据,另一种方法将该数据发送到客户端,但它们必须同时工作,也必须分开工作,有没有办法用线程做这种事情,如何做?

4

1 回答 1

2

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

您将有一个线程在无限循环中执行 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;
            }
        }
    }
}

我希望这个小技巧的例子会对你有所帮助。

于 2013-07-23T09:54:33.817 回答