How to instantiate the classes of a mono-threaded .dll library

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Some months ago I learned that the Varian library ESAPI is mono-threaded.
Consequently, If we try to instantiate a class, that is on another thread, from the GUI, we get an exception because classes, on a stack, cannot transfer thread ownership.
We can pass values over a multi-threaded environment but we cannot pass a class through different threads.

Recently I got bogged down with using Velocity API, another Varian library while attempting to build a WPF User Interface.
I do not know whether Velocity API is mono-threaded. I can only state that I successfully instantiated its classes and called its methods in a sequential Console-UI application.
Now I am trying to implement a WPF GUI offering the same functionalities offered by the Console UI application.
I use the same classes and methods I used in the Console UI application. But now I get Memory-Access-Violation thrown
on statements that call a Velocity API method. This phenomenon is not systematic, it does not occur always on the same statement, but it originates from a call of a Velocity API method.

I would like to know whether the erratic Memory-Acces Violations are symptomatic of dealing with a mono-threaded library from a different thread.
If this is the case, is there any workaround to avoid the exceptions?

Thank you in advance
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,245
Location
Chesapeake, VA
Programming Experience
10+
In C#, classes can never exist on the stack since classes are always accessed by reference because they always live in the memory heap -- never the stack.

Also the appropriate nomenclature is "single-threaded", not "mono-threaded". It also sounds like those objects have a thread affinity -- e.g. they should only be used on the thread that they were created on.

In general, WPF itself is single threaded where almost all the work is done on the primary UI thread. It also prefers that you only access the UI elements on the thread that they were created in (i.e. the UI thread). Yes, it takes advantage of thread pools for some work, but it's not that common that user written code will be running on those thread pools.

If you use async/await you can get into situations where your code will be running in one of the thread pool threads. In general, though the async/await knows how to carry over the SynchronizationContext into that thread pool so that it seems like you are running on the original thread you were on when you used the await. (More details in this link: Await, SynchronizationContext, and Console Apps ) Unfortunately, what won't be carried around with the SynchronizationContext will be any unmanaged objects that may have a particular thread affinity. It sounds like that library you are using is making use of unmanaged objects.

Anyway, those memory access violations are more often due to unmanaged objects expecting to find things still in particular memory locations, but the managed environment that C# code lives in has freed up the memory because of garbage collection, or because a reallocation has happened and the object has been moved to another location and the old location has been marked as invalid.

The way to fix issues like this is to write C# code as if you were writing C or C++ code. Keep track of each and every thing that you instantiate and/or allocated, and know exactly when things are destroyed or deallocated.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,245
Location
Chesapeake, VA
Programming Experience
10+
If you are comfortable with state machines, I suggest starting a thread and running a state machine on that thread. Within that thread is where you instantiate your objects with single threaded affinity. If you don't want to go full blown state machine, you could implement essentially a poor man's state machine within the thread and write things as if you were writing a console program, but in this case the inputs will be coming from another thread.

Let's say you had a dead simple Console program that looked something like this:
C#:
static int GetInput()
{
    var line = Console.ReadLine();
    return int.Parse(line);
}

static void Main()
{
    Console.WriteLine("Enter the first number");
    int first = GetInput();

    Console.WriteLine("Enter the second number");
    int second = GetInput();

    int sum = first + second;
    Console.WriteLine("The sum is {0}", sum);

    Console.WriteLine("Press Enter key to exit.");
    Console.ReadLine();
}

You could have something like this:
C#:
class AddNumbers
{
    public int Input { get; set; }
    public int Sum { get; private set; }
    public bool InputReady { get; set; }
    public bool SumReady { get; private set; }
    public bool Quit { get; set; }

    int GetInput()
    {
        while (!InputReady)
            Thread.Sleep(1000);

        int value = Input;
        InputReady = false;

        return value;
    }

    public void ThreadMain()
    {
        int first = GetInput();
        int second = GetInput();

        Sum = first + second;
        SumReady = true;

        while (!Quit)
            Thread.Sleep(1000);
    }
}

And so you would end up using that new class like:
C#:
class MyMainWindow : ...
{
    AddNumbers _addNumbers;
    Thread _thread;

    void MyMainWindow()
    {
        :
        _addNumbers = new AddNumbers();
        _thread = new Thread(_addNumbers.ThreadMain());
        _thread.Start();
    }

    void InputButton_Click(...)
    {
        _addNumbers.Input = int.Parse(_inputTextBox.Text);
        _addNumbers.InputReady = true;
    }

    void MyMainWindow_Paint(...)
    {
        if (_addNumbers.SumReady)
        {
            _sumTextBox.Text = _addNumbers.Sum.ToString();
            _addNumbers.Quit = true;
        }
    }
}

As a quick aside the, the really correct way is for an event to be fired by AddNumbers when the sum is ready, but I didn't want to bring in the complication that the event is now being fired off from the other thread. Another alternative is to implement INotifyPropertyChange, but again there's the issue that notification will come from another thread. So instead in this code I'm just polling for the sum ready state to determine when it can be shown to the user.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
In C#, classes can never exist on the stack since classes are always accessed by reference because they always live in the memory heap -- never the stack.

Also the appropriate nomenclature is "single-threaded", not "mono-threaded". It also sounds like those objects have a thread affinity -- e.g. they should only be used on the thread that they were created on.

In general, WPF itself is single threaded where almost all the work is done on the primary UI thread. It also prefers that you only access the UI elements on the thread that they were created in (i.e. the UI thread). Yes, it takes advantage of thread pools for some work, but it's not that common that user written code will be running on those thread pools.

If you use async/await you can get into situations where your code will be running in one of the thread pool threads. In general, though the async/await knows how to carry over the SynchronizationContext into that thread pool so that it seems like you are running on the original thread you were on when you used the await. (More details in this link: Await, SynchronizationContext, and Console Apps ) Unfortunately, what won't be carried around with the SynchronizationContext will be any unmanaged objects that may have a particular thread affinity. It sounds like that library you are using is making use of unmanaged objects.

Anyway, those memory access violations are more often due to unmanaged objects expecting to find things still in particular memory locations, but the managed environment that C# code lives in has freed up the memory because of garbage collection, or because a reallocation has happened and the object has been moved to another location and the old location has been marked as invalid.

The way to fix issues like this is to write C# code as if you were writing C or C++ code. Keep track of each and every thing that you instantiate and/or allocated, and know exactly when things are destroyed or deallocated.
Thank you.
I wrote some C++ some time ago as I was doing Monte Carlo simulations using Topas which is a wrapper for Geant4.
Topas has its own high-level language. However, I had to develop some extensions using Geant4 language which is C++. I was helped.
I do not know of any C# statement to control memory allocation other than "new".
I decided to declare all the variables (Lists, vectors, scalars) as "public static" as they are used by different code units belonging to different files.
I also stepped back and started to review the whole application and made some "improvements" but I could not complete this task as the servers at Mount Vernon Hospital are down starting today at 5 p.m. to Sunday morning. They are upgrading several s/w licenses.
In essence, I do not know of a NY specific technique to debug an event-driven application. It is difficult to follow the logic.

I will use this time to read something about binding.
I got the book "Pro WPF 4.5 in C#" by MacDonald.
I went directly to the 8th chapter about "binding" but I had to step back to an initial chapter as I have to get the nomenclature and basic concepts clear.



I am going
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
If you are comfortable with state machines, I suggest starting a thread and running a state machine on that thread. Within that thread is where you instantiate your objects with single threaded affinity. If you don't want to go full blown state machine, you could implement essentially a poor man's state machine within the thread and write things as if you were writing a console program, but in this case the inputs will be coming from another thread.

Let's say you had a dead simple Console program that looked something like this:
C#:
static int GetInput()
{
    var line = Console.ReadLine();
    return int.Parse(line);
}

static void Main()
{
    Console.WriteLine("Enter the first number");
    int first = GetInput();

    Console.WriteLine("Enter the second number");
    int second = GetInput();

    int sum = first + second;
    Console.WriteLine("The sum is {0}", sum);

    Console.WriteLine("Press Enter key to exit.");
    Console.ReadLine();
}

You could have something like this:
C#:
class AddNumbers
{
    public int Input { get; set; }
    public int Sum { get; private set; }
    public bool InputReady { get; set; }
    public bool SumReady { get; private set; }
    public bool Quit { get; set; }

    int GetInput()
    {
        while (!InputReady)
            Thread.Sleep(1000);

        int value = Input;
        InputReady = false;

        return value;
    }

    public void ThreadMain()
    {
        int first = GetInput();
        int second = GetInput();

        Sum = first + second;
        SumReady = true;

        while (!Quit)
            Thread.Sleep(1000);
    }
}

And so you would end up using that new class like:
C#:
class MyMainWindow : ...
{
    AddNumbers _addNumbers;
    Thread _thread;

    void MyMainWindow()
    {
        :
        _addNumbers = new AddNumbers();
        _thread = new Thread(_addNumbers.ThreadMain());
        _thread.Start();
    }

    void InputButton_Click(...)
    {
        _addNumbers.Input = int.Parse(_inputTextBox.Text);
        _addNumbers.InputReady = true;
    }

    void MyMainWindow_Paint(...)
    {
        if (_addNumbers.SumReady)
        {
            _sumTextBox.Text = _addNumbers.Sum.ToString();
            _addNumbers.Quit = true;
        }
    }
}

As a quick aside the, the really correct way is for an event to be fired by AddNumbers when the sum is ready, but I didn't want to bring in the complication that the event is now being fired off from the other thread. Another alternative is to implement INotifyPropertyChange, but again there's the issue that notification will come from another thread. So instead in this code I'm just polling for the sum ready state to determine when it can be shown to the user.
Thank you for all the tutorials you posted to help me.
I never heard of "State Machine" before. My understanding is that it is a technique to follow the runtime behaviour of event-driven applications.

I don't know how to implement a State-Machine with Visual Studio. I browsed through the documentation. It seems there exists a graphic way to implement it.
I'd rather get some answers from the Varian Velocity group before adding this further complex layer to my application.

I am reading the documentation you suggested about bindings.
I will post another question about a smaller problem I have with my WPF application.
Now I am stuck until the servers at Mount Vernon Hospital are up & running again.
Have a nice weekend
 

Latest posts

Top Bottom