dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.02k stars 1.16k forks source link

WPF multi-thread UI is not thread-safe #8764

Open vsfeedback opened 7 months ago

vsfeedback commented 7 months ago

This issue has been moved from a ticket on Developer Community.


[severity:It bothers me. A fix would be nice]
Hello,

We have WPF project where there are a 3 UI windows, each one runs on its own UI thread.
On project startup, the threads are created and by the way the 3 windows are created in parallel.

We noticed that the method InitializeComponent() is not thread-safe and causes an exception in the method CleanUpRequestedStreamList() within the file PakageParts.cs

In the following screenshot, we see that _requestedStreams.Count = 1 so the variable i should start from 0 but its value is 1 which means another thread modified it.

Bab6ec1230460465fb65c2a7709542095638370603241413162_20231201-154523-image

Is there any possibility to support multi-threaded UI in Wpf?

Thanks!


Original Comments

Feedback Bot on 12/4/2023, 07:18 AM:

(private comment, text removed)


Original Solutions

(no solutions)

pchaurasia14 commented 7 months ago

Could you please provide a sample application that reproduces the problem.

Kobi-Blade commented 7 months ago

WPF is based on a single-threaded apartment model, so yes, the UI thread is not thread-safe.

You might want to consider implementing some form of synchronization to ensure that _requestedStreams is not accessed by multiple threads at the same time.

Typical race condition, feel free to correct me if I'm wrong, but like pchaurasia14 said, share a sample where you can reproduce the issue to properly diagnose your issue.

lamzibbrahim commented 6 months ago

@Kobi-Blade @pchaurasia14

here is an sample

https://github.com/dotnet/wpf/issues/297

Yes, we implemented some logic to prevent cross-thread, but will be helpful if the prevention will be included in the future .Net (framework) releases. At least prevent crash.

Thank you!

miloush commented 6 months ago

Managed Threading Best Practices:

Do not make instance data thread safe by default. Adding locks to create thread-safe code decreases performance, increases lock contention, and creates the possibility for deadlocks to occur. In common application models, only one thread at a time executes user code, which minimizes the need for thread safety. For this reason, the .NET class libraries are not thread safe by default.

It sounds like you can fix your issue by having a static lock around InitializeComponent. You are the one deciding on creating windows on multiple threads, so you are the one who knows that they need to be synchronized. Why should the framework do it for everyone in all cases? Introducing such lock would effectively make the windows not load in parallel, so you could just not be loading them in parallel in the first place.

WPF is not thread safe and is not aiming to, on the contrary, it actively tries to prevent multi thread access using the dispatcher.

syntax-tm commented 6 months ago

While I agree with the locking likely being their main issue, WPF can have multiple Windows with their own UI thread. Here is a link to the documentation. Here's the relevant portion of the code:

private void NewThreadWindow_Click(object sender, RoutedEventArgs e)
{
    Thread newWindowThread = new Thread(ThreadStartingPoint);
    newWindowThread.SetApartmentState(ApartmentState.STA);
    newWindowThread.IsBackground = true;
    newWindowThread.Start();
}

private void ThreadStartingPoint()
{
    new MultiWindow().Show();

    System.Windows.Threading.Dispatcher.Run();
}

Basically, create a new background STA Thread and then call Dispatcher.Run() to start the Dispatcher. I created a sample project using that example.

Just to reiterate, I agree with their issue being a problem with locking that's their responsibility to solve. However, multiple UI threads is not a problem when done correctly.

Sample: MultiThreadedWindowTest.zip

Neme12 commented 5 months ago

Do you have this problem with .NET Framework WPF or .NET Core WPF? It's not clear from the original ticket. This repository is only for .NET Core WPF issues.