多线程C#

时间:2011-11-08 04:01:28

标签: c# multithreading

我正在尝试使用轨迹条在图像上应用亮度/对比度,因为应用图像需要很长时间。当滚动轨迹栏时,它不平滑,它在我的表格上落后。这是我的代码,这是用于从UI分离工作线程的正确方法(虽然用户体验没有改善)?

    private void bright_tbr_ValueChanged(object sender, EventArgs e)
    {
        brightness = bright_tbr.Value;
        contrast = contrast_tbr.Value;
        toolTip1.SetToolTip(bright_tbr, brightness.ToString());
        Thread thread = new Thread(new ThreadStart(applyBandC));
        thread.IsBackground = true;
        thread.Start();

    }
     private void applyBandC()
    {
        this.Invoke((MethodInvoker)delegate()
                {
                    lock (this)
                    {
                        create_pixmap(brightness, contrast, 0, 0, 255, 255);
                        Bitmap bmp1 = new Bitmap(bmp);
                        BitmapData data1 = bmp1.LockBits(new Rectangle(0, 0,                                                bmp1.Width, bmp1.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                        MapLUT(bmp1.Height, bmp1.Width, data1.Scan0);
                        bmp1.UnlockBits(data1);
                        pictureBox2.Image = bmp1;
                    }
                }
    );

    }

3 个答案:

答案 0 :(得分:2)

您的解决方案无法改善用户体验,因为您的整个"多线程"代码包含在this.Invoke中! Invoke的目的是在UI线程上执行委托 。将pictureBox2.Image = bmp1;部分除了传递给this.Invoke的委托之外的所有处理代码移动,它应该正常工作。

答案 1 :(得分:1)

正如minitech所说,在调用块中工作时,您仍然在阻止UI。您必须在后台准备位图并将其分配给前台。您还必须确保只有一个准备任务同时运行,并且您不希望在等待另一个updateTask时批量更新请求。 TPL可以帮助您,请参阅以下示例代码:

    private Task _runningTask;

    // only call this method from the UI!
    private void UpdateBitmap()
    {
        int brightness = bright_tbr.Value; 
        int contrast = contrast_tbr.Value;
        // only when not yet running
        if (_runningTask == null)
        {
            var ui = TaskScheduler.FromCurrentSynchronizationContext();

            _runningTask = Task.Factory.StartNew<Bitmap>(() =>
            {
                // prepare
                create_pixmap(brightness, contrast, 0, 0, 255, 255);
                Bitmap bmp1 = new Bitmap(bmp);
                BitmapData data1 = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                MapLUT(bmp1.Height, bmp1.Width, data1.Scan0);
                bmp1.UnlockBits(data1);
                return bmp1;
            }).ContinueWith(x =>
            {
                // assign
                pictureBox2.Image = x.Result;

                int newBrightness = bright_tbr.Value;
                int newContrast = contrast_tbr.Value;

                // If the value has changed in the meantime, update again
                if (newBrightness != brightness || newContrast != contrast)
                {
                    UpdateBitmap();
                }
                else
                {
                    _runningTask = null;
                }
            }, CancellationToken.None, TaskContinuationOptions.None, ui);
        }
    }

答案 2 :(得分:0)

这是一个Web应用程序或Windows应用程序(更具体地说是WPF)。如果它是基于WPF的应用程序,那么您可以使用Dispatcher类来执行非基于UI的任务,这些任务将在单独的线程上执行,一旦处理结束,结果将被推回到主UI线程。有关Dispatcher的更多信息:http://weblogs.asp.net/pawanmishra/archive/2010/06/06/understanding-dispatcher-in-wpf.aspx