multi threading C#

本文关键字:threading multi | 更新日期: 2023-09-27 18:13:41

我正在尝试使用跟踪条在图像上应用亮度/对比度,因为应用于图像需要很长时间。当轨迹条滚动时,它不平滑,它在我的表单上延迟了。这是我的代码,这是正确的方法分离工作线程从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;
                    }
                }
    );
    }

multi threading C#

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

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

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