【发布时间】:2011-02-03 11:54:32
【问题描述】:
谁能为我指出以下问题的有效解决方案?
我正在处理的应用程序需要通过 TCP 与在另一个系统上运行的软件进行通信。我发送到该系统的一些请求可能需要很长时间才能完成(最多 15 秒)。
在我的应用程序中,我有许多线程,包括主 UI 线程,它们可以访问与远程系统通信的 服务。只有一个服务实例可供所有线程访问。
我只需要允许一次处理一个请求,即它需要被序列化,否则 TCP 通信会发生不好的事情。
目前尝试的解决方案
最初我尝试使用带有静态对象的 lock() 来保护每个“命令”方法,如下所示:
lock (_cmdLock)
{
SetPosition(position);
}
但是我发现有时它不会释放锁,即使远程系统和 TCP 通信上存在超时。此外,如果来自同一个线程的两个调用(例如,用户双击一个按钮),那么它将通过锁定 - 在再次阅读有关锁定之后,我知道同一个线程不会等待锁定。
然后我尝试使用 AutoResetEvents 一次只允许一个呼叫。但是如果没有锁定,它将无法与多个线程一起使用。以下是我用来发送命令(来自调用线程)和处理命令请求(在自己的线程上在后台运行)的代码
private static AutoResetEvent _cmdProcessorReadyEvent = new AutoResetEvent(false);
private static AutoResetEvent _resultAvailableEvent = new AutoResetEvent(false);
private static AutoResetEvent _sendCommandEvent = new AutoResetEvent(false);
// This method is called to send each command and can run on different threads
private bool SendCommand(Command cmd)
{
// Wait for processor thread to become ready for next cmd
if (_cmdProcessorReadyEvent.WaitOne(_timeoutSec + 500))
{
lock (_sendCmdLock)
{
_currentCommand = cmd;
}
// Tell the processor thread that there is a command present
_sendCommandEvent.Set();
// Wait for a result from the processor thread
if (!_resultAvailableEvent.WaitOne(_timeoutSec + 500))
_lastCommandResult.Timeout = true;
}
return _lastCommandResult.Success;
}
// This method runs in a background thread while the app is running
private void ProcessCommand()
{
try
{
do
{
// Indicate that we are ready to process another commnad
_cmdProcessorReadyEvent.Set();
_sendCommandEvent.WaitOne();
lock (_sendCmdLock)
{
_lastCommandResult = new BaseResponse(false, false, "No Command");
RunCOMCommand(_currentCommand);
}
_resultAvailableEvent.Set();
} while (_processCommands);
}
catch (Exception ex)
{
_lastCommandResult.Success = false;
_lastCommandResult.Timeout = false;
_lastCommandResult.LastError = ex.Message;
}
}
我还没有尝试实现命令请求队列,因为调用代码期望一切都是同步的——即,在我发送下一个命令之前,上一个命令必须已经完成。
附加背景
远程系统上运行的软件是第 3 方产品,我无权访问它,它用于控制带有集成 XY 工作台的激光打标机。
我实际上使用的是旧版 VB6 DLL 与激光器通信,因为它具有用于格式化命令和处理响应的所有代码。此 VB6 DLL 使用 WinSock 控件进行通信。
【问题讨论】:
-
它控制激光!它是附在鲨鱼头上的吗?!?你有迷你我吗? ;)
标签: c# multithreading tcp