0

I'm in a situation where I have a particular sequence of operations that need to occur on the SAME THREAD, but the operations are a mix of Tasks, Observables, and various random code and method calls, including a try/catch. The kicker is it all needs to be executed on the same thread. For example...can you solve for this by rewriting the ExampleSequence method?:

    void SomeVoidMethod() { /* misc logic here */ }

    void SomeOtherVoidMethod() { /* misc logic here */ }

    void SomeExceptionHandlingMethod() { /* misc logic here */ }

    IObservable<int> SomeObservableProducingMethod()
    {
        /* something interesting here */
        return Observable.Return(3);
    }

    IObservable<Unit> SomeOtherObservableProducingMethod()
    {
        /* something interesting here */
        return Observable.Return(Unit.Default);
    }

    async Task ExampleSequence(Task someTask)
    {
        try
        {
            SomeVoidMethod();

            await someTask;

            var val = await SomeObservableProducingMethod().ToTask();

            if (val > 0)
                await SomeObservableProducingMethod().ToTask();

            SomeOtherVoidMethod();
        }
        catch (Exception)
        {
            SomeExceptionHandlingMethod();
        }
    }

EDIT: What's the underlying problem (you may be wondering)? I have some limitations on what existing code can be changed, and right now when working against a SQlite database the 2nd database operation is failing (it never returns) once I try to wrap the operations in a transaction. My assumption has been that it is a thread locking issue as SQlite has pretty rudimentary ways of locking the database for transactions...

EDIT2: As per @Nksoi's link in the comments, https://stackoverflow.com/a/24195827/1735721, I tried using an AsyncLock. That didn't fix the hang but I discovered it's the very first Observable being awaited that ends up waiting forever. So in the example above it would be this line:

var val = await SomeObservableProducingMethod().ToTask();

Is there something I should be passing in to the Reactive Extension observable or the ToTask extension method to promote thread consistency? Also, now thinking that it could be something inside the Akavache library (https://github.com/akavache/Akavache) that is causing the problem. Akavache is producing the observables. I will do some more debugging...

DennisWelu
  • 788
  • 13
  • 26
  • What do you mean by same thread. It is unclear. Do you mean in sequence, synchronously,...what? As you are awaiting the tasks they will all return to the thread when done. the non async methods do not go anywhere – Nkosi Aug 11 '17 at 20:35
  • Duplicate: https://stackoverflow.com/questions/14057721/continuation-task-in-the-same-thread-as-previous – zzxyz Aug 11 '17 at 20:51
  • You can also look into `BackgroundWorker` class and `Dispatcher` class if it's critical for some bizarre reason the UI thread launch each task individually, but into the same thread. – zzxyz Aug 11 '17 at 20:56
  • @Nkosi Yes they must all run in the same thread in that sequence. So like when something is awaited the calling thread continues on while the background thread does its thing.@zzxyz The UI thread is not significant here, it's all background work so should be on background thread. The referenced SO article is not duplicate - it only deals with Tasks not Observables. – DennisWelu Aug 11 '17 at 21:41
  • @Nkosi And I guess yeah when I say 'sequence' I'm not referring to an Observable sequence, just the logical progress in that synchronous order. Currently things are being "await"ed just to show the intended order of things, but the thread for all work is then not consistent throughout. – DennisWelu Aug 11 '17 at 21:46
  • 5
    @DennisWelu, Ok. This appears to be an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What is the ultimate goal you are trying to achieve? – Nkosi Aug 11 '17 at 21:47
  • @Nkosi Fair enough :-) I've added a summary of the underlying problem... – DennisWelu Aug 11 '17 at 21:55
  • @DennisWelu https://stackoverflow.com/questions/24186577/what-is-the-correct-usage-for-sqlite-on-locking-or-async – Nkosi Aug 11 '17 at 22:00
  • @DennisWelu so the crux is that it should be access by one thread at a time not necessarily on the same thread. – Nkosi Aug 11 '17 at 22:03
  • @DennisWelu - If you can limit your code to work purely in Rx then it is easy to restrict your code to running on a single thread. If you introduce tasks then it will go awry rather quickly. Take a look at the `EventLoopScheduler` - it's designed for exactly what you want to do. – Enigmativity Aug 13 '17 at 05:04
  • @DennisWelu - You should also give us a [mcve] that demonstrates that your code uses multiple threads. Then we can get that code to run on a single thread. Right now your question demands far too much work from us to expect anyone to answer it. – Enigmativity Aug 13 '17 at 05:05
  • @Enigmativity Yes I agree that would be better. But if someone already has had a similar experience or has purposefully mixed both Tasks and Observables on a common thread they would not need a sample to Solve it. That's what I was hoping for. – DennisWelu Aug 13 '17 at 17:59
  • @Enigmativity I've seen the EventLoopScheduler and agree if everything was in Rx it would be easier. Unfortunately there is some constraints on what can be changed here. I still need to take a closer look at Akavache code and plan to do that in the next few days. – DennisWelu Aug 13 '17 at 18:00
  • After debugging through Akavache I've realized that the problem is indeed not thread based. Akavache is doing automatic transactions for each operation in the API and I missed the "transaction already started" exception being thrown which was silently killing the background thread doing the operation. Thanks all for the ideas and helpful suggestions to improve the post. – DennisWelu Aug 16 '17 at 14:49

0 Answers0