JI在Visual Studio 2008中編寫了.NET C#Windows窗體應用程序,它使用信號量在按下「開始」按鈕時將多個作業作爲線程運行。Windows窗體在運行線程時掛起
遇到一個問題,表單在運行40分鐘或更長時間後進入逗號。日誌文件表明當前作業完成,它從列表中選擇一個新作業,並在那裏掛起。
我注意到當這種情況發生時,Windows窗體變得沒有響應。該表單正在其自己的線程中運行。
這是我使用的代碼的一個示例:
protected void ProcessJobsWithStatus (Status status)
{
int maxJobThreads = Convert.ToInt32(ConfigurationManager.AppSettings["MaxJobThreads"]);
Semaphore semaphore = new Semaphore(maxJobThreads, maxJobThreads); // Available=3; Capacity=3
int threadTimeOut = Convert.ToInt32(ConfigurationManager.AppSettings["ThreadSemaphoreWait"]);//in Seconds
//gets a list of jobs from a DB Query.
List<Job> jobList = jobQueue.GetJobsWithStatus(status);
//we need to create a list of threads to check if they all have stopped.
List<Thread> threadList = new List<Thread>();
if (jobList.Count > 0)
{
foreach (Job job in jobList)
{
logger.DebugFormat("Waiting green light for JobId: [{0}]", job.JobId.ToString());
if (!semaphore.WaitOne(threadTimeOut * 1000))
{
logger.ErrorFormat("Semaphore Timeout. A thread did NOT complete in time[{0} seconds]. JobId: [{1}] will start", threadTimeOut, job.JobId.ToString());
}
logger.DebugFormat("Acquired green light for JobId: [{0}]", job.JobId.ToString());
// Only N threads can get here at once
job.semaphore = semaphore;
ThreadStart threadStart = new ThreadStart(job.Process);
Thread thread = new Thread(threadStart);
thread.Name = job.JobId.ToString();
threadList.Add(thread);
thread.Start();
}
logger.Info("Waiting for all threads to complete");
//check that all threads have completed.
foreach (Thread thread in threadList)
{
logger.DebugFormat("About to join thread(jobId): {0}", thread.Name);
if (!thread.Join(threadTimeOut * 1000))
{
logger.ErrorFormat("Thread did NOT complete in time[{0} seconds]. JobId: [{1}]", threadTimeOut, thread.Name);
}
else {
logger.DebugFormat("Thread did complete in time. JobId: [{0}]", thread.Name);
}
}
}
logger.InfoFormat("Finished Processing Jobs in Queue with status [{0}]...", status);
}
//形式方法
public void Process()
{
try
{
//sets the status, DateTimeStarted, and the processId
this.UpdateStatus(Status.InProgress);
//do something
logger.Debug("Updating Status to [Completed]");
//hits, status,DateFinished
this.UpdateStatus(Status.Completed);
}
catch (Exception e)
{
logger.Error("Exception: " + e.Message);
this.UpdateStatus(Status.Error);
}
finally {
logger.Debug("Relasing semaphore");
semaphore.Release();
}
我試圖
private void button1_Click(object sender, EventArgs e)
{
buttonStop.Enabled = true;
buttonStart.Enabled = false;
ThreadStart threadStart = new ThreadStart(DoWork);
workerThread = new Thread(threadStart);
serviceStarted = true;
workerThread.Start();
}
private void DoWork()
{
EmailAlert emailAlert = new EmailAlert();
// start an endless loop; loop will abort only when "serviceStarted" flag = false
while (serviceStarted)
{
emailAlert.ProcessJobsWithStatus(0);
// yield
if (serviceStarted)
{
Thread.Sleep(new TimeSpan(0, 0, 1));
}
}
// time to end the thread
Thread.CurrentThread.Abort();
}
//job.process()記錄我可以將文件記錄到文件中以檢測問題發生的位置,但到目前爲止,我還無法確定發生了什麼。失去對Windows窗體的控制使我認爲這與處理作業無關。有任何想法嗎?
解決方案:使用RedGate ANTS進行性能分析正在產生問題。直接運行時不會發生。
嘗試運行Visual Studio並在掛起時插入代碼(僅使用暫停按鈕)。然後使用線程窗口來檢查所有等待的線程。 – Grzenio 2010-03-11 16:43:48