Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 190391
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T16:15:09+00:00 2026-05-11T16:15:09+00:00

My multi-threading knowledge is still pretty rudimentary, so would really appreciate some pointers here.

  • 0

My multi-threading knowledge is still pretty rudimentary, so would really appreciate some pointers here. I have an interface, IOperationInvoker (from WCF) which has the following methods:

IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)

Given a concrete implementation of this interface, I need to implement the same interface, whilst calling the underlying implementation in a seperate Thread. (in case you’re wondering why, the concrete implmentation calls a legacy COM object which needs to be in a different apartment state).

At the moment, I’m doing something like this:

public StaOperationSyncInvoker : IOperationInvoker {
   IOperationInvoker _innerInvoker;
   public StaOperationSyncInvoker(IOperationInvoker invoker) {
       this._innerInvoker = invoker;
   } 


    public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
    {
        Thread t = new Thread(BeginInvokeDelegate);
        InvokeDelegateArgs ida = new InvokeDelegateArgs(_innerInvoker, instance, inputs, callback, state);
        t.SetApartmentState(ApartmentState.STA);
        t.Start(ida);
        // would do t.Join() if doing syncronously
        // how to wait to get IAsyncResult?
        return ida.AsyncResult;
    }

    public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
    {
        // how to call invoke end on the 
        // thread? could we have wrapped IAsyncResult
        // to get a reference here?
        return null;
    }

    private class InvokeDelegateArgs {
        public InvokeDelegateArgs(IOperationInvoker invoker, object instance, object[] inputs, AsyncCallback callback, object state)
        {
            this.Invoker = invoker;
            this.Instance = instance;
            this.Inputs = inputs;
            this.Callback = callback;
            this.State = state;
        }

        public IOperationInvoker Invoker { get; private set; }
        public object Instance { get; private set; }
        public AsyncCallback Callback { get; private set; }
        public IAsyncResult AsyncResult { get; set; }
        public Object[] Inputs { get; private set; }
        public Object State { get; private set; }
    }
    private static void BeginInvokeDelegate(object data)
    {
        InvokeDelegateArgs ida = (InvokeDelegateArgs)data;
        ida.AsyncResult = ida.Invoker.InvokeBegin(ida.Instance, ida.Inputs, ida.Callback, ida.State);
    }
}

I’m thinking I need to wrap up the returned AsyncResult with my own, so I can get back to the thread we’ve spooled up… but honestly I’m a little out of my depth. Any pointers?

Many thanks,

James

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-11T16:15:09+00:00Added an answer on May 11, 2026 at 4:15 pm

    The easiest way to implement a synchronous method asynchronously is to put it into a delegate, and use the BeginInvoke and EndInvoke methods on the resulting delegate. This will run the synchronous method on a threadpool thread, and BeginInvoke will return an IAsyncResult implementation, so you don’t have to implement the guts of it. However, you do need to smuggle a little extra data into the IAsyncResult returned by IOperationInvoker.InvokeEnd. You could do that easily by creating an implementation of IAsyncResult that delegates everything to an inner IAsyncResult, but has an extra field to contain the delegate, so that when the IAsyncResult instance is passed to InvokeEnd, you can access the delegate to call EndInvoke on it.

    However, after closer reading of your question, I see that you need to use an explicit thread with COM settings etc.

    What you need to do is properly implement IAsyncResult. Almost everything follows from this, since the IAsyncResult will contain all the bits needed for synchronization.

    Here’s a very simple, but not terribly efficient, implementation of IAsyncResult. It encapsulates all the essential features: passing arguments, a synchronization event, callback implementation, propagating exceptions from async task and returning result.

    using System;
    using System.Threading;
    
    class MyAsyncResult : IAsyncResult
    {
        object _state;
        object _lock = new object();
        ManualResetEvent _doneEvent = new ManualResetEvent(false);
        AsyncCallback _callback;
        Exception _ex;
        bool _done;
        int _result;
        int _x;
    
        public MyAsyncResult(int x, AsyncCallback callback, object state)
        {
            _callback = callback;
            _state = state;
            _x = x; // arbitrary argument(s)
        }
    
        public int X { get { return _x; } }
    
        public void SignalDone(int result)
        {
            lock (_lock)
            {
                _result = result;
                _done = true;
                _doneEvent.Set();
            }
            // never invoke any delegate while holding a lock
            if (_callback != null)
                _callback(this); 
        }
    
        public void SignalException(Exception ex)
        {
            lock (_lock)
            {
                _ex = ex;
                _done = true;
                _doneEvent.Set();
            }
            if (_callback != null)
                _callback(this);
        }
    
        public object AsyncState
        {
            get { return _state; }
        }
    
        public WaitHandle AsyncWaitHandle
        {
            get { return _doneEvent; }
        }
    
        public bool CompletedSynchronously
        {
            get { return false; }
        }
    
        public int Result
        {
            // lock (or volatile, complex to explain) needed
            // for memory model problems.
            get
            {
                lock (_lock)
                {
                    if (_ex != null)
                        throw _ex;
                    return _result;
                }
            }
        }
    
        public bool IsCompleted
        {
            get { lock (_lock) return _done; }
        }
    }
    
    class Program
    {
        static void MyTask(object param)
        {
            MyAsyncResult ar = (MyAsyncResult) param;
            try
            {
                int x = ar.X;
                Thread.Sleep(1000); // simulate lengthy work
                ar.SignalDone(x * 2); // demo work = double X
            }
            catch (Exception ex)
            {
                ar.SignalException(ex);
            }
        }
    
        static IAsyncResult Begin(int x, AsyncCallback callback, object state)
        {
            Thread th = new Thread(MyTask);
            MyAsyncResult ar = new MyAsyncResult(x, callback, state);
            th.Start(ar);
            return ar;
        }
    
        static int End(IAsyncResult ar)
        {
            MyAsyncResult mar = (MyAsyncResult) ar;
            mar.AsyncWaitHandle.WaitOne();
            return mar.Result; // will throw exception if one 
                               // occurred in background task
        }
    
        static void Main(string[] args)
        {
            // demo calling code
            // we don't need state or callback for demo
            IAsyncResult ar = Begin(42, null, null); 
            int result = End(ar);
            Console.WriteLine(result);
            Console.ReadLine();
        }
    }
    

    It’s important for correctness that client code can’t see the IAsyncResult implementation, otherwise they might access methods like SignalException inappropriately or read Result prematurely. The class can be made more efficient by not constructing the WaitHandle implementation (ManualResetEvent in the example) if it’s not necessary, but this is tricky to get 100% right. Also, the Thread and ManualResetEvent can and should be disposed of in the End implementation, as should be done with all objects that implement IDisposable. And obviously, End should check to make sure that it has gotten an implementation of the right class to get a nicer exception than a cast exception. I’ve left these and other details out as they obscure the essential mechanics of the async implementation.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 124k
  • Answers 124k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer Are you running on OS 3.0? I saw the same… May 12, 2026 at 1:19 am
  • Editorial Team
    Editorial Team added an answer It looks like you need to register Apache::Session::Memcached with Apache::Session::Wrapper,… May 12, 2026 at 1:19 am
  • Editorial Team
    Editorial Team added an answer Use DATENAME or DATEPART: SELECT DATENAME(dw,GETDATE()) -- Friday SELECT DATEPART(dw,GETDATE())… May 12, 2026 at 1:19 am

Related Questions

I'm still a little unclear and when to wrap a lock around some code.
I just purchased C++ GUI Programming with Qt4 and after reading the code samples
I am writing a C++ application and would like to request several data files
Does ehcache support multi-threading by default or does it require any configuration changes? On

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.