开发者

How do I break a loop that is running in different thread using a TimerCallback in C#?

I am writing a game server that has a time limit. I will be accepting input accross a socket until the timer is done. I am using a forever loop to receive data from the client.

whil开发者_如何学编程e(true)
{
    socket.Receive(buffer);
} 

I need to break out of this loop when the time limit ends.

Sorry I don't think I am being specific enough.

I have two players sending and receiving data asynchronously. The timer is used to keep track of the time for both players. I need to end the reception of data from both players and give back statistics about their game at the end of the timer.


The best way to handle this is for the thead with the timer to call a stop method in the class where the socket receive method is. This class will have a AutoResetEvent member instance and in the while for the socket read check the event to see if you need to stop:

public class SomeClass {
    AutoResetEvent _stopEvent = new AutoResetEvent(false);
    Socket _socket;
    public void StopReceive() {
        _stopEvent.Set();
    }
    private void SomeMethod() {
        _socket.ReceiveTimeout = 5000;  // In milliseconds
        while(!_stopEvent.WaitOne(0)){
                _socket.Receive(buffer);
        }
    }
}

Edit: If you have two sockets for the two players on two different threads, with the third thread handling the timeout then the code in all three threads need access to the same event, and change the event to a ManualResetEvent. What I am not sure about is if you have one class that handles the timer thread, and another class that handles the socket read threads for the two players, or if they are handled by one class. If they are separate classes then for the above code you could pass the event in the constructor:

public class SomeClass {
    ManualResetEvent _stopEvent;
    Socket _socket;
    public SomeClass(ManualResetEvent stopEvent) {
        _stopEvent = stopEvent;
    }
    private void SomeMethod() {
        _socket.ReceiveTimeout = 5000;  // In milliseconds
        while(!_stopEvent.WaitOne(0)){
                _socket.Receive(buffer);
        }
    }
}

The timer thread could now call the Set() method in the ManualResetEvent instance and both while loops would terminate.


Have a watchdog timer close the socket when timeout expires. It will cause a SocketException on your socket.Receive call so be prepared to catch it. I use the same mechanism for different purposes.

Solution 2: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.receivetimeout.aspx but I don't know if it can be applied to your case.

Or, else, you might query the Available property of the socket that indicates how many bytes are ready to be read. But this involves a polling/spinlock, which is bad for performance. Even if you wanted to use a semaphore, which gives you the opportunity to set a maximum timeout, you still need "somebody" to release it when data is available


I was Thinking that instead of creating an infinite loop. I could possibly use a non-blocking socket.

while(stillTime)
{
    if(socket.Available > 0)
    socket.Recieve(buffer);
}

And when timer goes off set stillTime to false.

Is this a better solution?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜