的问题?我有一个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();一种在将数据发送到客户端之前处理数据的方法,但问题是这两种方法同时在数据库中的相同表上工作,所以我不希望得到数据库锁或其他一些数据库错误,并且使用定时器是方法进入碰撞,一个方法处理数据,另一个方法将数据发送到客户端,但它们必须同时工作,也需要单独工作,有没有办法用线程做这种事情以及如何做?
答案 0 :(得分:1)
如何摆脱问题的想法可能是双缓冲线程循环。 这是实现游戏循环的一个很好的概念,但它也可以满足您的需求。
您将有一个线程在无限循环中执行PROCESS_DATA,另一个线程在无限循环中执行SEND_DATA_TO_CLIENT。你有两个缓冲区。这可以是包含PROCESS_DATA方法返回的信息的任何类或结构。
首先锁定SEND_DATA_TO_CLIENT循环,直到PROCESS_DATA线程填充buffer_1。然后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;
}
}
}
}
我希望这个小巧的例子可以帮助你。