繁体   English   中英

多线程程序不响应

[英]Multithreaded program does not respond

我有两个线程,除了主ui线程。 它们都具有无限循环,其中之一准备位图,而另一个则将更改应用于ui。 问题是,当我启动程序时,它不响应任何输入。

    private WriteableBitmap _bmp;
    private byte[] _pixelData;
    private Image _img;
    private int _stride;
    private int _width, _height;
    const int BYTES_OF_PIXEL = 4;
    private Random _random;
    private Mutex _mutex = new Mutex();

    public MainWindow()
    {
        InitializeComponent();
        Width = 480;
        Height = 320;
        canvas.Width = Width;
        canvas.Height = Height;
        WindowStartupLocation = WindowStartupLocation.CenterScreen;
        _random = new Random();
        _width = (int)this.Width;
        _height = (int)this.Height;

        var pixelCount = _width * _height;

        _bmp = new WriteableBitmap(_width, _height, 96, 96, PixelFormats.Bgra32, null); // writeable bmp
        _pixelData = new byte[pixelCount * BYTES_OF_PIXEL]; // all pixels
        _stride = _width * BYTES_OF_PIXEL; // bytes per row
        _img = new Image(); // displayed image

        RenderOptions.SetBitmapScalingMode(_img, BitmapScalingMode.LowQuality);
        RenderOptions.SetEdgeMode(_img, EdgeMode.Aliased);
        canvas.Children.Add(_img);

        var bufferThread = new Thread(PrepareScreenWrapper);
        var renderThread = new Thread(RenderScreenWrapper);

        bufferThread.Start();
        renderThread.Start();
    }

    private void PrepareScreen()
    {
        while (true)
        {
            var a = (byte)_random.Next(255);
            var r = (byte)_random.Next(255);
            var g = (byte)_random.Next(255);
            var b = (byte)_random.Next(255);
            var color = Color.FromArgb(a, r, g, b);

            for (var y = 0; y < _height; y++)
            {
                for (var x = 0; x < _width; x++)
                {
                    var index = (y * _stride) + (x * 4);
                    _pixelData[index] = color.B;
                    _pixelData[index + 1] = color.G;
                    _pixelData[index + 2] = color.R;
                    _pixelData[index + 3] = color.A;
                }
            }

            _mutex.WaitOne();
            _bmp.WritePixels(new Int32Rect(0, 0, _width, _height), _pixelData, _stride, 0);
            _mutex.ReleaseMutex();
        }
    }

    private void RenderScreen()
    {
        while (true)
        {
            _mutex.WaitOne();
            _img.Source = _bmp;
            _mutex.ReleaseMutex();
        }
    }

    private delegate void PrepareScreenCallback();
    private void PrepareScreenWrapper()
    {
        var prepareScreenCallback = new PrepareScreenCallback(PrepareScreen);
        Application.Current.Dispatcher.BeginInvoke(prepareScreenCallback, DispatcherPriority.Render);
    }
    private delegate void RenderScreenCallback();
    private void RenderScreenWrapper()
    {
        var renderScreenCallback = new RenderScreenCallback(RenderScreen);
        Application.Current.Dispatcher.BeginInvoke(renderScreenCallback, DispatcherPriority.Render);
    }

看完您的代码后,我对其进行了重构,并使用TPLTasks进行了更好的线程管理。 我还将Buffer和Render合并为互斥体,仅处理复杂的问题,并且两者都可以在单个函数中发生,因为它已经脱离了UI线程。

注意:Task.Delay()停止向UI线程发送垃圾邮件,这将导致其无响应。 您必须小心不要使UI线程超载,因为这可能会导致UI锁定。

TPL中的任务为多线程提供了更好的api。 我强烈建议您阅读它们。

private WriteableBitmap _bmp;
    private byte[] _pixelData;
    private Image _img;
    private int _stride;
    private int _width, _height;
    const int BYTES_OF_PIXEL = 4;
    private Random _random;
    private Mutex _mutex = new Mutex();

    public MainWindow()
    {
      InitializeComponent();
      Width = 480;
      Height = 320;
      canvas.Width = Width;
      canvas.Height = Height;
      WindowStartupLocation = WindowStartupLocation.CenterScreen;
      _random = new Random();
      _width = (int)this.Width;
      _height = (int)this.Height;

      var pixelCount = _width * _height;

      _bmp = new WriteableBitmap(_width, _height, 96, 96, PixelFormats.Bgra32, null); // writeable bmp
      _pixelData = new byte[pixelCount * BYTES_OF_PIXEL]; // all pixels
      _stride = _width * BYTES_OF_PIXEL; // bytes per row
      _img = new Image(); // displayed image

      RenderOptions.SetBitmapScalingMode(_img, BitmapScalingMode.LowQuality);
      RenderOptions.SetEdgeMode(_img, EdgeMode.Aliased);
      canvas.Children.Add(_img);

      var progress = new Progress<object>(_ =>
      {
        _bmp.WritePixels(new Int32Rect(0, 0, _width, _height), _pixelData,_stride, 0);
        _img.Source = _bmp;
      });

      var bufferTask = Task.Factory.StartNew(() => Process(progress));
    }

    private void Process(IProgress<object> progress)
    {
      while (true)
      {
        var a = (byte) _random.Next(255);
        var r = (byte) _random.Next(255);
        var g = (byte) _random.Next(255);
        var b = (byte) _random.Next(255);
        var color = Color.FromArgb(a, r, g, b);

        for (var y = 0; y < _height; y++)
        {
          for (var x = 0; x < _width; x++)
          {
            var index = (y*_stride) + (x*4);
            _pixelData[index] = color.B;
            _pixelData[index + 1] = color.G;
            _pixelData[index + 2] = color.R;
            _pixelData[index + 3] = color.A;
          }
        }

        progress.Report(null);
        Task.Delay(1000);
      }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM