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

Don't capture synchronization context in DiskWriterQueue #2447

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

alexbereznikov
Copy link

This addresses #2446

Task.Factory.StartNew tries to use task scheduler from the current task, so TaskScheduler.Default needs to be passed here.

Copy link
Collaborator

@pictos pictos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see the value of not capture the syncronization context, but this will be a breaking change. From the linked issue, it's caused because your project uses a custom SyncronziationContext, but that doesn't happen on UI frameworks, that implements its own syncContext, so I that doesn't prove that the issue is in your SyncContext implementation and not on LiteDb?

@alexbereznikov
Copy link
Author

@pictos As I described in related issue (#2446), breaking change was introduced after 5.0.17 - Task.Run (which uses default task scheduler) has been changed to Task.Factory.StartNew (that uses a current task scheduler by default). More precisely, breaking changes were made in this commit - f21cd84

So this PR aims to revert this breaking change, not to introduce one.

Regardless of whether our custom context is implemented correctly, I don't think it is a good idea to execute writer queue on a captured context (e g UI context). I would say, it rather highlights the issue.

@pictos
Copy link
Collaborator

pictos commented Jun 6, 2024

So, looking more closely to the implementation I strongly believe that the issue is more than having it capturing the current task's TaskScheduler.
The task is being created with LongRunning flag, and uses an async delegate, and you may know that those two doesn't fit togheter.

So the first thing we should change here is to make the ExecuteQueue a void method, and block the created thread on the async operations or rethink all this engine, which I believe will not be done on this PR if we choose this path.

edit: Did a PoC using the main implementation and it will not flow the UI context, adding the TaskScheduler or not will not change the behavior, will just go throw UI thread if you pass TaskScheduler.FromCurrentSynchronizationContext(), so I would say that your PR will not fix the issue at the end

Copy link
Collaborator

@pictos pictos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After talking with @mbdavid, I could understand the idea behind this member. So the fix is something completely different from your implementation.

No matter if you pass the TaskScheduler as parameter or not, it will not run on the UI Thread. The fix is making the ExecuteQueue method a void method and all the implementation should be a block code, that's not use any asynchronous API.

Also, for improvement, remove the lock object on the task instantiation and use an interlockedExchange method to verify if there's a need to create a task.

With that the code will behave as expected, it will run on a deticated thread and will not touch any kind of syncContext, taskScheduler or threadPool Thread.

Let me know if you want to perform these changes, otherwise I'll do it. And thanks for your hard work so far❣️

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

Successfully merging this pull request may close these issues.

None yet

3 participants