代码之家  ›  专栏  ›  技术社区  ›  Benjamin Ortuzar

运行线程时Windows窗体挂起

  •  0
  • Benjamin Ortuzar  · 技术社区  · 16 年前

    JI在visualstudio2008中编写了一个.netc#Windows窗体应用程序,当按下Start按钮时,它使用一个信号量作为线程运行多个作业。

    它遇到了这样一个问题:表单在运行40分钟或更长时间后变成逗号。日志文件表明当前作业已完成,它从列表中选择一个新作业,并挂起。

    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);
    
    }
    

    //窗体方法

    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();
            }
    

    //作业流程()

     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();
                }
    

    我试着把我能做的记录到一个文件中,以检测问题发生在哪里,但到目前为止,我还不能确定问题发生在哪里。失去对Windows窗体的控制使我认为这与处理作业无关。有什么想法吗?

    解决方案:

    1 回复  |  直到 16 年前
        1
  •  3
  •   Spencer Ruport    16 年前

    我首先看到的是你的 Thread.CurrentThread.Abort() 打电话。这是不必要的。让函数退出,线程将正常关闭。

    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());
       // Should have exit here.
    }
    logger.DebugFormat("Acquired green light for JobId: [{0}]", job.JobId.ToString());
    

    第三件事是您的工作线程正在调用一个函数,该函数只是为jobs循环中的每个作业创建线程。如果一个作业没有完成(假设这会导致一个作业从队列中删除,因为我在任何地方都看不到该代码。)在DoWork从睡眠中醒来之前,它将遍历同一个作业并尝试为它创建另一个线程。