执行threadloop中的最后一个线程

时间:2013-02-21 06:55:41

标签: c# multithreading

我在C#4.0中实现一个漫画阅读器,并从一个图像浏览 由于我实施了一些流程,下一段时间需要一些时间。

因此,我以UI线程将显示的方式实现它 首先是后台线程正在处理的未处理图像 图像,稍后将替换未处理的图像。

一切正常但现在,有些用户会疯狂地想点击下一步 图像连续,这导致后台工作程序进行处理 所有这些点击并显示所有图像。

我想要的是:如果用户多次点击,我想要背景 worker只处理最后一个线程。

我做了什么:现在,我已经实现了一个功能来检查 活动线程数,如果活动线程大于1, 后台线程不会处理但返回上一个图像(那个 不好,因为未经处理的图像将是前面的一个索引)

如果您有意,请像初学者一样向我解释!

private void button4_Click(object sender, EventArgs e)
{

    Bitmap b = new Bitmap(this.CurrImage);

           if (!shutdown)
          {
            process_updateThread = new Thread(new ThreadStart(process_update));
            process_updateThread.Start();
          }

    pictureBox1.Image = b; //image will be replaced by worker thread image 
    pictureBox1.Location = ImageEdit.CalculateLocationImage(b);
    SetBackColor(b);
    ShowPageCount();
    updateNavButtons(); 
}


void StopThread()
{
    if(((IEnumerable)System.Diagnostics.Process.GetCurrentProcess().Threads).OfType<System.Diagnostics.ProcessThread>()
        .Where(t => t.ThreadState == System.Diagnostics.ThreadState.Running).Count() > 1) 
    shutdown = true;
    else shutdown = false;
}

2 个答案:

答案 0 :(得分:0)

我假设您的长时间运行过程是process_update。

您必须在运行下一个process_updates之前停止所有正在运行的process_updates。但是不要使用BOOLEAN VARIABLE去做 !!!您必须使用同步对象。最有可能的是它应该是ManualResetEvent。

更新:

这个非常简单的示例可以让您了解多线程和线程管理

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;


namespace WindowsFormsExamples
{
    public partial class OnlyOneThread : Form
    {
        List<ManualResetEvent> threadStopEvents;    //This will hold stop events for running threads

        public OnlyOneThread()
        {
            InitializeComponent();
            threadStopEvents = new List<ManualResetEvent>();
        }

        private void runThreadBtn_Click(object sender, EventArgs e)
        {
            ManualResetEvent evt = new ManualResetEvent(false);
            ParameterizedThreadStart ts = new ParameterizedThreadStart(this.ThreadFunc);
            Thread t = new Thread(ts);
            t.Start(evt);
        }

        private delegate void UptadeThreadCountDelegate();   //This delegate is used by Invoke method
        private void UpdateThreadCount()
        {
            threadcountLbl.Text = threadStopEvents.Count.ToString();
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            //We must stop threads if they are still running

            lock (threadStopEvents)  // locking prevents simultaneous list access
            {
                foreach (ManualResetEvent evt in threadStopEvents)
                {
                    evt.Set(); //signal all events
                }
            }
        }


        //This is thread function
        private void ThreadFunc(Object obj)
        {
            ManualResetEvent stopEvent = obj as ManualResetEvent; //cast an object that was passed by Thread.Start()

            lock (threadStopEvents) // locking prevents simultaneous list access
            {
                foreach (ManualResetEvent evt in threadStopEvents)
                {
                    evt.Set(); //signal all events for all other threads to stop
                }

                threadStopEvents.Add(stopEvent);  //Put our event on list
            }

            if (this.IsHandleCreated) // This is necessary for invocation
                this.Invoke(new UptadeThreadCountDelegate(this.UpdateThreadCount));  //Invoke counter update

            for (int i = 0; i < 60; i++) // this will run about 1 minute
            {
                if (stopEvent.WaitOne(0)) // Tests stopEvent and continues
                {
                    //Stop signaled!!! exit!
                    break;
                }

                Thread.Sleep(1000); //Sleep 1 second
            }
            lock (threadStopEvents) // locking prevents simultaneous list access
            {
                threadStopEvents.Remove(stopEvent); //remove stop event from list
            }
            if (this.IsHandleCreated) // This is necessary for invocation
                this.Invoke(new UptadeThreadCountDelegate(this.UpdateThreadCount));  //Invoke counter update
        }
    }
}

如果要运行此示例,则必须创建WindowsForms项目并在表单上添加Button和label,然后使用此代码绑定到这些控件。注意一下form方法的调用。当来自非GUI线程时,这是必要的。

答案 1 :(得分:0)

我看不出这个问题的简单解决方案......多线程绝非易事。就个人而言,我建议遵循(生产者/消费者情况的一种偏差):

  • 首先有一个通用计数器,表示当前要渲染的图像(可以是一个简单的int,按下每个按钮递增)

一个很好地锁定的ImageMonitor,它有一个方法:

  • 添加要渲染的图像(使用当前计数器) - &gt;按下每个按钮会发生这种情况
  • 检索应渲染的图像(包括图像的计数器)
  • 处理渲染图像

现在我们需要一个连续工作的后台线程,它循环并在每次迭代中检查ImageMonitor以处理最新图像,处理图像并将其返回给ImageMonitor(包括计数器)

当ImageMonitor从背景渲染器获取渲染图像时,它可以检查图像是否具有正确的计数器值,如果是,那么它可以将当前图像与渲染图像交换

这个解决方案显然有点复杂。但是,它应该工作。我对其他(更简单的)解决方案感兴趣。

祝你好运