Есть клиент-серверное приложение. Клиент время от времени посылает сообщения на сервер (сервер их обрабатывает и сохраняет в БД). Для этого был создан класс скажем Server:MarshalByRefObject
в котором собственно идет отсылка сообщения Server.SendToServer().
Далее на клиенте время от времени отсылаються сообщения на сервер:
private static Thread m_SendToServerThread;
private static int m_WaitDelay=1000*60*12;
private static System.Threading.Timer m_WaitForSend;
public Send(Queue m_Queue)
{
bool isNotSent=true;
while (m_Queue.Count>0)
{
SendArgs argsToSend=m_Queue.Dequeue() as SendArgs;
while (isNotSent)
{
try
{
SendToServerClass sts=new SendToServerClass(argsToSend);
m_SendToServerThread=new Thread(new ThreadStart(sts.SendToServerMethod));
m_SendToServerThread.Start();
m_WaitForSend.Change(m_WaitDelay, Timeout.Infinite);
m_SendToServerThread.Join();
m_WaitForSend.Change(Timeout.Infinite, Timeout.Infinite);
m_SendToServerThread=null;
if (sts.isError && sts.Exception!=null)
{
throw sts.Exception;
}
if (sts.IsSent)
{
isNotSent=false;
}
}
catch (Exception ex)
{
Thread.Sleep(12000);//Send failed. Try again in 12 seconds
}
}
}
}
private static void onWaitTimer(object p_state)
{
if (m_SendToServerThread!=null && m_SendToServerThread.IsAlive)
{
m_SendToServerThread.Abort();
}
}
public class SendToServerClass
{
private MessageEventArgs m_argsToSend;
private bool m_isSent;
private bool m_WasError;
private Exception m_Exception;
public bool IsSent
{
get { return m_isSent; }
}
public bool isError
{
get { return m_WasError; }
}
public Exception Exception
{
get { return m_Exception; }
}
public SendToServerClass(MessageEventArgs p_argsToSend)
{
m_isSent=false;
m_WasError=false;
m_Exception=null;
m_argsToSend=p_argsToSend;
}
public void SendToServerMethod()
{
try
{
Server.Instance.SendToServer(m_argsToSend);
m_isSent=true;
}
catch (Exception ex)
{
m_Exception=ex;
m_WasError=true;
m_isSent=false;
}
}
}
В большинстве случаев все работает нормально, но где-то раз в три дня интенсивного исспользования m_SendToServerThread подвисает и соответственно остальные сообщения не отсылаються, так как мы ждем отсылки сообщения m_SendToServerThread.Join(); (ждать надо обезатьельно, так как порядок важен). Для решения этой проблемы ввел System.Threading.Timer, но m_SendToServerThread.Abort(); не всегда убивает поток. В тех случаях когда не убивает, поток просто переходит в состояние ThreadState.AbortRequested и никогда из него не выходит

Научился воспроизводить это зависание (если клиент и БД находяться на одном компе, а сервер на втором, и в момент отсылки сообщения выключить компьютер с клиентом, то это зависание и происходит, даже если потом востановить соединение), так что тестировать возможно. Сервер не умирает, и до него возможно достучаться с клиента. Вопрос в том, как убить этот поток, чтоб не происходило этого зависания.
з.ы. Извиняюсь за такой обьемный вопрос, просто никак не могу решить эту проблему
Здравствуйте, Abuserrr, Вы писали:
<skipped>
A>В большинстве случаев все работает нормально, но где-то раз в три дня интенсивного исспользования m_SendToServerThread подвисает и соответственно остальные сообщения не отсылаються, так как мы ждем отсылки сообщения m_SendToServerThread.Join(); (ждать надо обезатьельно, так как порядок важен). Для решения этой проблемы ввел System.Threading.Timer, но m_SendToServerThread.Abort(); не всегда убивает поток. В тех случаях когда не убивает, поток просто переходит в состояние ThreadState.AbortRequested и никогда из него не выходит
Научился воспроизводить это зависание (если клиент и БД находяться на одном компе, а сервер на втором, и в момент отсылки сообщения выключить компьютер с клиентом, то это зависание и происходит, даже если потом востановить соединение), так что тестировать возможно. Сервер не умирает, и до него возможно достучаться с клиента. Вопрос в том, как убить этот поток, чтоб не происходило этого зависания.
A>з.ы. Извиняюсь за такой обьемный вопрос, просто никак не могу решить эту проблему
Хм...
Если это настолько критично, может попробывать "бросить" этот повисшый поток и создать другой заново (предварительно конечно сделав все возможное для удаления повисшего)...
Возможно, итоге (по какому-то внутреннему таймауту) повысший поток и отвалится...
Но так можно поступить только если уже ничего больше не помогает... и последить первое время за расходом памяти и ресурсов....
Здравствуйте, Abuserrr.
Посмотрите
здесьАвтор: TK
Дата: 17.07.06
, возможно найдете полезную информацию.
Здравствуйте, tyger, Вы писали:
T>Хм...
T>Если это настолько критично, может попробывать "бросить" этот повисшый поток и создать другой заново (предварительно конечно сделав все возможное для удаления повисшего)...
T>Возможно, итоге (по какому-то внутреннему таймауту) повысший поток и отвалится...
T>Но так можно поступить только если уже ничего больше не помогает... и последить первое время за расходом памяти и ресурсов....
В принципе временное решение такое и есть. Бросить подвисший поток, предварительно вызвав для него аборт (сделал с помощью промежуточного потока, модифицировав SendToServerClass)
public class SendToServerClass
{
private MessageEventArgs m_argsToSend;
private bool m_isSent;
private bool m_WasError;
private Exception m_Exception;
private Thread m_SendInClass;
public bool IsSent
{
get { return m_isSent; }
}
public bool isError
{
get { return m_WasError; }
}
public Exception Exception
{
get { return m_Exception; }
}
public SendToServerClass(MessageEventArgs p_argsToSend)
{
m_isSent=false;
m_WasError=false;
m_Exception=null;
m_argsToSend=p_argsToSend;
}
public void SendToServerMethod()
{
try
{
m_SendInClass=new Thread(new ThreadStart(Send));
m_SendInClass.Start();
m_SendInClass.Join();
m_isSent=true;
}
catch (Exception ex)
{
if (m_SendInClass!=null && m_SendInClass.IsAlive)
{
m_SendInClass.Abort();
}
m_Exception=ex;
m_WasError=true;
m_isSent=false;
}
}
private void Send()
{
try
{
Server.Instance.SendToServer.SendMessageToServerSync(m_argsToSend);
}
catch (Exception ex)
{
m_Exception=ex;
m_WasError=true;
m_isSent=false;
}
}
}
Недостаток такой, что поток, который делает Server.Instance.SendToServer так и продолжает жить (хоть и в редких случаях, но все же). И в таком случае при закрытии приложения, оно продолжает висеть в процессах
И еще вопрос, когда я делаю m_SendInClass.Abort(); в SendToServerMethod что первое должно выполниться, кетч в методе Send или продолжиться выполнение кетча в SendToServerMethod? Или все это будет происходить паралельно и приведет к неоднозначности?
Здравствуйте, Abuserrr, Вы писали:
A>Недостаток такой, что поток, который делает Server.Instance.SendToServer так и продолжает жить (хоть и в редких случаях, но все же). И в таком случае при закрытии приложения, оно продолжает висеть в процессах
Попробуйте у потока выставить IsBackground = true;
... << RSDN@Home 1.2.0 alpha rev. 0>>