Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

need advice in multythread #91

Open
epsi1on opened this issue Nov 3, 2024 · 3 comments
Open

need advice in multythread #91

epsi1on opened this issue Nov 3, 2024 · 3 comments

Comments

@epsi1on
Copy link
Contributor

epsi1on commented Nov 3, 2024

Hi,
If i want to use WriteableBitmapEx in a multi thread app, which a single thread is responsible for rendering an image in real-time, very much like rendering a game, but not exactly like that. just like one.
The problem is the main UI thread is different than rendering thread and i'll get the exception by wpf which says owner thread only can access the bitmap. if I create the WriteableBitmap in the render thread, then UI cannot access it and vice versa.

I was wondering if you guys have any suggestion for my case?

Thanks

@DDDDDragon
Copy link

I have the same problem, i want to draw a writeableBitmap by multiple threads to increase the draw speed, but seem like it cannot work

@epsi1on
Copy link
Contributor Author

epsi1on commented Nov 6, 2024

Seems wpf have a strict diplomacy in cross thread access, which every call is checked with DispatcherObject.VerifyAccess() and DispatcherObject.CheckAccess(), even when it is not needed.
The way this library for example draws a line, is first create an instance of BitmapContext struct ,which is not public structure. This structure is not thread sensitive, but when a new instance of BitmapContext is creating in the constructor it tries to access the WriteableBitmap's dependency properties which i think that causes the error.
There are two solutions i think. source code should be edited:

  • use Dispatcher.Invoke() when reading the DependencyProperty s of WriteableBitmap
  • mark the BitmapContext as public (which is currently internal it is alread public ) and make same extension methods from WriteableBitmap like WriteableBitmap.DrawLineAa for BitmapContext too. i mean add a new method of BitmapContext.DrawLine() to the library. this also do not work unless edit some code int the BitmapContext constructor.

first solution need least effort, but not so much general
second solution need more effort but general, also i think improves the performance as for every line draw it do not creates am instance of BitmapContext.
I think it could be pull request. @reneschulte, could you please let us know your opinion about this? this is more like a architectural plan. If it is OK with you, I can do the code and make the pull request...
Thanks

@epsi1on
Copy link
Contributor Author

epsi1on commented Nov 6, 2024

after exploring the code, i've found a way:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
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;

namespace WriteableBitmapExMultythreadExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        WriteableBitmap Bitmap;


        public MainWindow()
        {
            InitializeComponent();

            var w = 500;
            var h = 500;

            Bitmap = BitmapFactory.New(w, h);


            bmp.Source = Bitmap;

            var ctx = Bitmap.GetBitmapContext();

            var thr = new Thread(DrawLine);            thr.Start();            thr.Join();

            //DrawLine();

            ctx.Dispose();
            //Bitmap.AddDirtyRect(new Int32Rect(0, 0, w, h));
        }

        public void DrawLine()
        {
            Bitmap.DrawLineAa(20, 20, 400, 400, Colors.Black, 2);
        }

    }
}

if you call var ctx = Bitmap.GetBitmapContext(); in the main thread, you can do edits in another threads and finally when you call ctx.Dispose(); changes would be applied.
seems the WritebleBitmapEx is managing the multy threaded access with some extra cost.
I think better to let user handle the complexity, as discussed in #92.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants