Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke a function on parent thread in .NET?

I have a .NET class library containing a class with a method that performs some lengthy operation. When a client calls this method it should perform the lengthy operation on a new thread in order to avoid blocking the caller. But once the method finishes it should execute some code on the main thread. In a WinForms application I could have used the System.Windows.Forms.Control.Invoke method but this is not my case. So how can I achieve this in C#?

like image 548
Darin Dimitrov Avatar asked Nov 06 '08 19:11

Darin Dimitrov


3 Answers

You can invoke a function on a specific thread by using a System.Windows.Threading.Dispatcher object (from the WindowsBase assembly).

For example:

public class ClassCreatedBySomeThread
{
    Dispatcher dispatcher = Dispatcher.CurrentDispatcher; 

    public void SafelyCallMeFromAnyThread(Action a)
    {
       dispatcher.Invoke(a);
    }
} 
like image 168
cdiggins Avatar answered Nov 04 '22 11:11

cdiggins


I found a simple solution to the problem :

My COM object is declared like this:

public class Runner
{
    public void Run(string executable, object processExitHandler)
    {
        ThreadPool.QueueUserWorkItem(state =>
        {
            var p = new Process()
            {
                StartInfo = new ProcessStartInfo()
                {
                    FileName = executable
                }
            };
            p.Start();
            while (!p.HasExited)
            {
                Thread.Sleep(100);
            }

            state
                .GetType()
                .InvokeMember(
                    "call", 
                    BindingFlags.InvokeMethod, 
                    null, 
                    state, 
                    new object[] { null, p.ExitCode }
                );
        }, processExitHandler);
    }
}

And in my HTML page I use it like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head><title>ActiveXRunner</title>    
    <script type="text/javascript">
    function runNotepad() {
        var ax = new ActiveXObject('ActiveXRunner.Runner');
        ax.Run('c:\\windows\\notepad.exe', h);
    }

    function h(exitCode) {
        alert('exitCode = ' + exitCode);
    }
    </script>
</head>
<body>
    <a href="#" onclick="runNotepad();">Run notepad and show exit code when finished</a>
</body>
</html>
like image 12
Darin Dimitrov Avatar answered Nov 04 '22 10:11

Darin Dimitrov


If a thread has to be able to execute some bit of code (usually in the form of a delegate) posted to it by another thread, it will have to basically be waiting for those instructions. What else is your main thread doing? It's not that hard to build an equivalent of the event loop (basically you'd have a producer/consumer queue of delegates) but you need to be aware that you can't just interrupt the main thread and say "do this now".

Why does this have to execute on the main thread?

like image 11
Jon Skeet Avatar answered Nov 04 '22 10:11

Jon Skeet