I am trying to update a writeablebitmap by using multithreading, however I do not manage to get the ProgressChanged Event trigger any change at all to the UI. It is although on the verge, since once the RunWorkerCompleted event is called the UI updates. Have I miss understood the purpose of the ProgressChanged event or what is the matter?
Code for progresschanged is as follows:
private void BgWorkerMap_ProgressChanged_Handler(object sender, ProgressChangedEventArgs progressChangedArgs)
{
TestBitmap[7].Wb.AddDirtyRect(new Int32Rect(args[7].BgWorkerProperties.ProccessedX, args[7].BgWorkerProperties.ProccessedY, 256, 256));
TestBitmap[7].Wb.Unlock();
Src = TestBitmap[7].Wb;
TestBitmap[7].Wb.Lock();
}
Here is the full code Im using. If you try it out you will see at after 3 secs the UI will be updated (Added a thread sleep 1000ms / loop)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Testmultithredabitmap
{
public partial class MainWindow : INotifyPropertyChanged
{
private readonly BackgroundWorker worker;
private readonly Random random = new Random();
private WriteableBitmap src;
public WriteableBitmap Src
{
get { return src; }
set
{
if (Equals(value, src)) return;
src = value;
NotifyPropertyChanged("Src");
}
}
private class WorkerArgs
{
public int Width { get; set; }
public int Height { get; set; }
public IntPtr BackBuffer { get; set; }
}
WorldMapFloor[] TestBitmap = new WorldMapFloor[14];
public MainWindow()
{
InitializeComponent();
DataContext = this;
Src = new WriteableBitmap(256, 256, 96, 96, PixelFormats.Bgr32, null);
for (int i = 0; i < TestBitmap.Length; i++)
{
TestBitmap[i] = new WorldMapFloor(i);
TestBitmap[i].Wb.Lock();
}
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += WorkerOnDoWork;
worker.ProgressChanged += BgWorkerMap_ProgressChanged_Handler;
worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted;
worker.RunWorkerAsync(TestBitmap);
}
private void WorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
{
TestBitmap[7].Wb.AddDirtyRect(new Int32Rect(0, 0, 256 * 3, 256));
TestBitmap[7].Wb.Unlock();
Src = TestBitmap[7].Wb;
//TestBitmap[7].Wb.Lock();
}
private void WorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
WorldMapFloor[] args = (WorldMapFloor[])doWorkEventArgs.Argument;
var width = args[7].BgWorkerProperties.Stride;
int index = 0;
while (true)
{
int startXCord = (index) * 256;
int startYCord = (0) * 256;
int filrStartIndexInBuffer = startXCord + startYCord * 256;
args[7].BgWorkerProperties.ProccessedX = startXCord;
args[7].BgWorkerProperties.ProccessedY = startYCord;
Thread.Sleep(1000);
unsafe
{
var buffer = (int*)args[7].BgWorkerProperties.pBackBuffer;
for (var x = 0; x < 256; ++x)
{
for (var y = 0; y < 256; ++y)
{
buffer[filrStartIndexInBuffer + x + y * (width / 4)] = random.Next();
}
}
}
worker.ReportProgress(0, args);
++index;
if (index == 3) break;
}
}
private void BgWorkerMap_ProgressChanged_Handler(object sender, ProgressChangedEventArgs progressChangedArgs)
{
TestBitmap[7].Wb.AddDirtyRect(new Int32Rect(args[7].BgWorkerProperties.ProccessedX, args[7].BgWorkerProperties.ProccessedY, 256, 256));
TestBitmap[7].Wb.Unlock();
Src = TestBitmap[7].Wb;
TestBitmap[7].Wb.Lock();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class BgWorkerMapProperties
{
public int ProccessedX;
public int ProccessedY;
public IntPtr pBackBuffer;
public int Stride;
public BgWorkerMapProperties(WriteableBitmap wb, int floorZ)
{
// Get a pointer to the back buffer.
pBackBuffer = wb.BackBuffer;
Stride = wb.BackBufferStride;
}
}
public class WorldMapFloor
{
public WriteableBitmap Wb = new WriteableBitmap(256 * 8, 256 * 8, 96, 96, PixelFormats.Bgr32, null);
public BgWorkerMapProperties BgWorkerProperties;
public string[] Files = null;
public WorldMapFloor(int floorZ)
{
BgWorkerProperties = new BgWorkerMapProperties(Wb, floorZ);
}
}
}
}
Thanks on advance, from a desperate WPF programmer.