我为客户端(Windows Phone 8)提供了以下3种简化方法 - 我正在使用的服务器C#app:
private object sockLock = 1;
private System.Threading.Timer _timer = new Timer(onTimer);
void _sock_MessageReceived( ... )
{
lock(sockLock)
{
if( something ) //the server received the packet, so i can stop the timer
_timer.Change(Timeout.Infinite, Timeout.Infinite);
}
}
void onTimer( ... )
{
bool sendRequst = false;
lock(sockLock)
{
if ( conditions from critical section )
sendRequest = true;
}
if(sendRequest)
SendRequest( ... ); //replay the packet
}
async void SendRequest(Request req) //also called from GUI or user input
{
byte[] data = req.ToByteArray();
if (data.Length == 0)
return;
bool lockTaken = false;
Monitor.Enter(sockLock, ref lockTaken);
if(!lockTaken)
{
Debug.WriteLine("Monitor.Enter failed !!!");
return;
}
try
{
DataWriter dw = await GetSockStreamAsync(); //doesn't use lock in any way, it's just a lazy init
lastReq = req;
dw.WriteBytes(data);
await dw.StoreAsync();
await dw.FlushAsync();
_timer.Change(10, Timeout.Infinite);
}
finally
{
Monitor.Exit(sockLock); //here it throws exception
}
}
长话短说:我正在向服务器发送一些UDP数据包,服务器也会响应它收到的最后一个SEQ值。发送数据包后,我启动一个计时器,如果服务器没有及时响应,我重播该数据包。
在除SendRequest方法之外的所有方法中,我都可以使用锁,因此无法忘记释放sockLock。
然而,在SendRequest中,我需要'等待',因此我无法使用锁定,因为我没有多想,所以同步的解决方案是使用Monitor。
现在,当从GUI调用SendRequest时,它可以工作,但是当它从onTimer函数调用时,它会在Monitor.Exit(sockLock)处抛出SynchronizationLockException。
Object synchronization method was called from an unsynchronized block of code.
at System.Threading.Monitor.Exit(Object obj)
at AbsMouse.AbsMouseClient.<SendRequestAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()}
“等待”是否会导致任何隐藏的副作用,或者我在此问题上缺少的其他任何内容?
提前致谢!