【发布时间】:2014-01-18 07:29:11
【问题描述】:
我有一个线程数组,它们从私有消息队列中检索消息,将它们反序列化为日志条目对象,并将日志条目对象的属性存储在 SQL Server 数据库表日志条目中。
这是我创建和启动线程的代码。
try
{
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(new ThreadStart(this.logEntriesToDatabase));
threads[i].Start();
}
}
catch (ThreadStateException ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK,MessageBoxIcon.Error);
return;
}
catch (OutOfMemoryException ex)
{
MessageBox.Show("Not Enough Memory Please Close Other Applications To Continue", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
每个线程执行一个函数 logentriestodatabase()
while(true)
{
#region Retrieves Message from Message Queue and Deserialized it to a Log Entry Object.
#region Sleep Time for Current Thread
Thread.Sleep(180);
#endregion
#region Check to See Whether Queue Is Empty. If so go back to start of while loop
if (q1.GetAllMessages().Length == 0)
{
continue;
}
#endregion
#region Message retrieval and Deserialization Code
System.Messaging.Message m = this.q1.Receive();
m.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
LogEntry lg = BinaryLogFormatter.Deserialize(m.Body.ToString());
#endregion
#endregion
#region Insert Log Entry Into Database
#region Define a new SQL Connection with username and password specified in App.Config, an SQL Transaction and database queuries
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LogReader"].ConnectionString);
SqlTransaction transaction;
string query_insert_into_logentry = "INSERT INTO logentry" + "(message, priority, processname, severity, accountid, ipaddress, servername, servertype, timestamp)" + "VALUES ('" + lg.Message + "'," + lg.Priority + ",'" + lg.AppDomainName + "','" + lg.Severity.ToString() + "','" + lg.ExtendedProperties["AccountID"].ToString() + "','" + lg.ExtendedProperties["IpAddress"].ToString() + "','" + lg.ExtendedProperties["ServerName"].ToString() + "','" + lg.ExtendedProperties["ServerType"].ToString() + "','" + lg.TimeStamp.ToString() + "')";
string query_insert_into_category = "INSERT INTO category (category) VALUES ('" + lg.Categories.First().ToString() + "')";
#endregion
#region Begin and Terminates Transaction and Closes the SQL Connection Catches any SQL Exception Thrown and Displays Them
try
{
conn.Open();
transaction = conn.BeginTransaction();
new SqlCommand(query_insert_into_logentry, conn, transaction).ExecuteNonQuery();
new SqlCommand(query_insert_into_category, conn, transaction).ExecuteNonQuery();
transaction.Commit();
conn.Close();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
return;
}
#endregion
#endregion
}
现在每当我运行这个程序时,消息队列变空时,程序就会挂起。 我似乎无法弄清楚为什么。我试图给 q1.Receive() 函数一个 TimeSpan ,但这没有用。我用 180 毫秒的时间调用了 sleep 方法,但它仍然不起作用。可能是由于 q1.Receive 方法在遇到空队列时将当前线程发送到阻塞状态。
请帮助我对想法持开放态度。
【问题讨论】:
-
顺便说一句,您可以在 C# 中使用 cmets,您不必使用区域向代码发送垃圾邮件
-
为什么不在while 语句中使用条件
q1.GetAllMessages().Length > 0? (而不是while(true)我的意思) -
更好的是,用正确命名的函数替换区域。使用这么多区域是一种非常糟糕的代码气味
-
您应该查看带有
using块的IDisposable模式。如果出现任何问题,您的数据库代码将泄漏句柄。即使一切都很好,甚至可能在释放手柄方面落后。 “挂起”是什么意思?你的主线程挂了吗?如果是这样,它是做什么的,你没有发布代码......
标签: c# .net multithreading msmq enterprise-library