0

I have a 3rd party library that needs to be executed in a WPF application. I know this code down bellow dose not start as WPF. Might be worth keep in mind, just have tried to break out the issue as a smaller case.

Anyway, their aint much documentation or I can do about the 3rd party library, more than it needs to be used.

Because some task are pretty long when it comes to processing and time I thought It would be a good idea to have these managed on a separate thread to avoid locking UI. So my thoughts are to have most of the work that can be done in a separate processing thread, and have the 3rd party library be called on the main UI thread where it is safe and then return data to the thread for further processing. This is because the code used in there might not be fully thread safe to be called from anywhere, as so far this has been totally out of luck.

So my current thoughts about this was to dispatch what is needed from the 3rd party library thread/task to what is registered as the main UI thread, and have collect the data and return it to the processing thread.

PreProcessing -> 3pl -> PostProcessing.

This is not fully working right now as there are no exceptions or info of why this dose not work. As it just dies at when running InvokeOnMainTread in the ThirdPartyTest().

What is missing here to get this invoke to be passed as ok?

Any ideas or help would be greatly appreciated.

using System;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace TestTPL
{
    class Program
    {      
        static void Main(string[] args)
        {
            ThreadMethods methods = new ThreadMethods();
            methods.Execute();
        }
    }

    public class ThreadMethods
    {
        private static ThirdPartyCaller caller;
        public async void Execute()
        {
            //Doing some pre processing...

            //Reach for 3rd party lib
            caller = new ThirdPartyCaller();
            int taskRes = await TestTask();

            //Do some more processing of data
            
        }

        private async Task<int> TestTask()
        {
            return await Task.Run(() =>
            {
                int project = caller.ThirdPartyTest();
                return project;
            });
        }
    }

    public class ThirdPartyCaller
    {
        private readonly Dispatcher dispatcher;

        public ThirdPartyCaller()
        {
            dispatcher = Dispatcher.CurrentDispatcher;
        }

        protected TResult InvokeOnMainTread<TResult>(Func<TResult> action)
        {
            return dispatcher.Invoke(action);
        }

        public int ThirdPartyTest()
        {
            return InvokeOnMainTread(() =>
            {
                //Represents calculations done by a third pary library
                return 2 + 6;
            });

       
        }
    }
}


Jonas Lindahl
  • 752
  • 10
  • 24
  • Could you add more info about the API of the third-party library? Giving an example of a class, some methods/properties of this class, and how would you use this class from the UI thread if freezing was not an issue, might ne helpful. – Theodor Zoulias Jan 24 '22 at 18:36
  • In [this](https://stackoverflow.com/questions/58379898/c-sharp-moving-database-to-a-separate-thread-without-busy-wait/58397942#58397942) answer you can find a `SingleThreadTaskScheduler` class, that might give you some ideas. – Theodor Zoulias Jan 25 '22 at 05:11

1 Answers1

0

Your Main function calls an asynchronous function (execute) but does not wait for it that call to complete. You either need to add a .Wait() to the execute task or await it (however older versions of C# will not let you make Main async). Currently, your program is exiting before your task even runs.

Also, the main thread is likely blocked by await TestTask() in your Execute function. Because you are setting dispatcher from the ThirdPartyCaller constructor while it runs on the main thread, Dispatcher.Invoke may never execute the delegate because the thread is blocked waiting for TestTask to complete. If you want to keep he "invoke on main" functionality, you may need to remove the await from TestTask.

John Glenn
  • 1,469
  • 8
  • 13
  • Not sure completing the code with passing along TResult is enough. VS tells the name can be simplified and there by can removing it. With or with out it, it still dose not get pass this point of the code. – Jonas Lindahl Jan 24 '22 at 21:48
  • You are trying to invoke the action on the main thread, but the main thread is blocked by your "await TestTask()" call. You either need to not await that call, or you need to invoke the action on another thread. The same thread cannot be both waiting on your TestTask and running your action. – John Glenn Jan 24 '22 at 22:06
  • I removed both of the "await" and just let it run in a "while(true)" to not kill it to soon. Code never hits the return value from what has been invoked. – Jonas Lindahl Jan 24 '22 at 22:52
  • Just curious - why are you trying invoke the third party library on the main thread in the first place? – John Glenn Jan 24 '22 at 23:17
  • methods.Execute() isn't awaited either, but it is asynchronous. Main is likely exiting early, as well. – John Glenn Jan 25 '22 at 02:37