I have a class that in one of its methods creates a new thread that makes some http requests, serializes the results, packs them up in an event object and then it Should call broadcast an event returning its data. but I can't figure out how.

the class is not a form, so it doesn't have the invoke method, and I need to pass data back to the class. I'm stuck on this.

here is a stripped down version

class someclass
{
       public someclass()
      {

       }
//my event
     public delegate void onTimelineHandler(object sender ,TimelineArgs e);
     public event onTimelineHandler OnTimelineRecieved;

        private void TimelineAsyncStart(string url)
        {
            Thread myAsyncer = new Thread(new ParameterizedThreadStart(doTimelineAsync));

            string[] objar = new string[] { url, username, password };
            myAsyncer.Start(objar);
            
        }

 private void doTimelineAsync(object objar)
        {

            string[] sa2 = (string[])objar;
            string url = sa2[0];
            string username = sa2[1];
            string password = sa2[2];

          //some stuff happens here

             TimelineArgs targs = new TimelineArgs(myobject);

          [B]//here I need to call the event on the class that created    this thread, passing to that event the TImelineArgs object.[/B]

        }


]

I could really use some help on this, threading is not my things, I learned using background worker, guess I could have done that here, but really i would like to know how this is done.

Recommended Answers

All 9 Replies

If the receivers of the event absolutely must have the information back into thier own thread (like a Windows App sometimes does) then you would handle the invoke for arguments in those receiving threads.
Move your delegate out into the name space so that receivers outside of this class can use it. Really your choice, they can use fully qualified naming to get to it as well.

When the thread is ready to push the data into the event, then check to see if it is assigned, and then call it.

The receiver needs to check to see if invoke is required. Your Something class may itself be called from another thread, so to be safe, let the receivers deal with it.
(see more below this code snip)

using System.Threading;

namespace WindowsFormsApplication1
{
    public delegate void onTimelineHandler(object sender, TimelineArgs e);
    class SomeClass
    {
        public SomeClass() { }
        public event onTimelineHandler OnTimelineRecieved;

        public void TimelineAsyncStart(string url)
        {
            Thread myAsyncer = new Thread(new ParameterizedThreadStart(doTimelineAsync));
            string[] objar = new string[] { url, "username", "password" };
            myAsyncer.Start(objar);
        }

        private void doTimelineAsync(object objar)
        {
            string[] sa2 = (string[])objar;
            string url = sa2[0];
            string username = sa2[1];
            string password = sa2[2];
            object myobject = "411"; // just something to play with
            //some stuff happens here
            if( OnTimelineRecieved != null )
            {
                TimelineArgs targs = new TimelineArgs(myobject);
                OnTimelineRecieved(null, targs);
            }
        }
    }

    public class TimelineArgs
    {
        public object Something = null;
        public TimelineArgs(object something)
        {
            Something = something;
        }
    }

}

If the receivers need to invoke it, then use something like this:

void cs_OnTimelineRecieved(object sender, TimelineArgs e)
        {
            if ( this.InvokeRequired )
            {
                onTimelineHandler d = new onTimelineHandler(cs_OnTimelineRecieved);
                this.Invoke(d, new object[] { sender, e });
            }
            else
            {
                string something = e.Something.ToString();
                MessageBox.Show(something);
            }
        }

I work with many threads in an app, and they exchange information all the time without invoke. It is when I need to update a some non-thread safe object that I need to use Invoke.

Hope this helps,
Jerry

I managed to get it to work. I honestly really don't understand *how* it works, but I can implement the code behind doing it.

start()
{
Func<[I]Params[/I], [I]params[/I][I]returnValue[/I]> method = [I]Methodname[/I];
IAsyncResult res = method.BeginInvoke(Params, Params, new AsyncCallback([I]methodthatCatchesEndInvoke[/I]), [I]IDK object[/I]);
}

methodthatCatchesEndInvoke(IAsyncResult res)
{
[I]ReturnValue[/I] answer = method.EndInvoke(res);
}

I don't know any other way to do this. This works well, only problem is that you have to invoke the result again before you can even use it. And that makes it a lot of work to use. If anyone knows how to get around that. i would appreciate more information.

Thanks jerry, but calling the event from the 2nd thread always fails in my code. but I guess its because I haven't disabled the cross thread warnings.

I really don't like having to check if an invoke is required in the event handler on the form, I know an Invoke will always be required because that events exists in my code for the sole reason of threading. But I don't know how to get around it.

as I posted above, I did find a way to just run the methods asynchronously easy returning the data. but I still have the problem of having to invoke the response data in order to use it and I wish there was a way around it.

I think you are stuck with Invoke because that is how C# moves the object pointer into the memory stack of the thread that wants to use it.
A little trick on sending the event to something that does not know how to check for InvokeRequired is to replace sender with null, and check that when it hits the handler. Replace sender in the delegate with this, or some non null value so it knows not to re-throw the invoke.

Good Luck

Thanks jerry, but calling the event from the 2nd thread always fails in my code. but I guess its because I haven't disabled the cross thread warnings.

I really don't like having to check if an invoke is required in the event handler on the form, I know an Invoke will always be required because that events exists in my code for the sole reason of threading. But I don't know how to get around it.

as I posted above, I did find a way to just run the methods asynchronously easy returning the data. but I still have the problem of having to invoke the response data in order to use it and I wish there was a way around it.

Jerry -- I'm not knocking on your example, it was great, I just wanted to point one thing out:

if( OnTimelineRecieved != null )
            {
                TimelineArgs targs = new TimelineArgs(myobject);
                OnTimelineRecieved(null, targs);
            }

Technically some believe that is not "thread safe" because in the time between checking if the event is not null and calling it someone in another thread could null it -- resulting in a null reference exception. Likewise the events are usually being null'd when the object is being disposed and the event shouldn't be called anyway -- which will likely result in another exception somewhere else in the code. I just wanted to throw that in there.

The "recommended way" or "best practices" way to call a delegate:

public event EventHandler SomeEvent;
    private void SampleEvent()
    {
      var del = this.SomeEvent;
      if (del != null)
        del(this, new EventArgs());
    }

Diamonddrawe,
I have posted a bit of code that holds an HTTP connection open and fires off an event as it receives data. The code is posted here:
http://www.daniweb.com/forums/post1024173.html#post1024173

That code fires off an event from the thread pool so it needs to be invoked back on to the GUI thread, just as Jerry mentioned and demonstrated. I handled it very similarly to the way he did:

void reader_OnLineReceived(object sender, TwitterLineReceivedArgs e)
    {
      this.Invoke(new MethodInvoker(
        delegate()
        {
          System.Threading.Interlocked.Increment(ref linesRead);
          textBox1.Text += e.Line;
          label1.Text = string.Format("Lines Read: {0:F0}", linesRead);
        }
      ));
    }

In this case I didn't check for InvokeRequired since I know that event will always be called from another thread.

I hope this helps out some. If it didn't then try uploading a project so we can take a look.

One more thing.... is there any reason you were manually creating a thread instead of using the thread pool?

Thread myAsyncer = new Thread(new ParameterizedThreadStart(doTimelineAsync));

I noticed in a later post you switched over to using .BeginInvoke() which is probably the way I would approach it. Creating your own thread can guarantee execution where as the ThreadPool queues up software threads until it has time for execution. If you manually create a thread that is not marked as a background thread it will also stop your application from closing until that thread has been aborted.

Thanks,

firstly, I manually created the thread because I have no Idea what I am doing. Threading is so new to me. I have used the backgroundworker class before, as it handles it all for you and even accepts and returns and object by default. but I needed a direct implementation any my gui was freezing during http requests.

you know, I never did get that whole anonymous delegate thing, so I still invoke on my main thread's event handler using

this.Invoke(new UpdateTextCallback(this.UpdateText), new object[] { e.TimeLine_Statuses });

then create a delegate and a method

        public delegate void UpdateTextCallback(statuses text);

        private void UpdateText(statuses text)
        {            statuses twitStatuses = text;

            foreach (statusesStatus stats in twitStatuses.status)
            {
                richTextBox1.Text = richTextBox1.Text + "\n" + stats.text + " - user: " + stats.user[0].name;
            }
        }

but I will try that anonymous approach.

Also, I didn't really understand why in your link that you only did the read response stream in Async and not the entire request. But either way I needed more, my http request ironically also a twitter api wrapper, makes a request for a user's "friendtimeline" and receives the xml, then deserializes it based on a schema class and returns that "statuses" object to the UI where it can easily get any information about the post.

I got both the synchronous and Asynchronous methods in my class when I get to using it in my newest hobby project I will be able to choose which best suits my needs.

I have gotten it working, just that whole invoke delegate with a callback thing on the form that I don't like.

question! Would calling the event from a delegate not require me to invoke the event data on the GUI thead?

public event EventHandler SomeEvent;
    private void SampleEvent()
    {
      var del = this.SomeEvent;
      if (del != null)
        del(this, new EventArgs());
    }

and thanks again for all the handy info.

No .. You can call any method from any thread. The problem is that if the code implemented and subscribed to that delegate modify a control on the GUI thread .. and the delegate is called from another thread. It is up to the person implementing the code subscribed to the event to handle cross-thread calls.

>>Also, I didn't really understand why in your link that you only did the read response stream in Async and not the entire request

The reason I did this is how the exception would surface. The way I implemented it will cause an exception to be thrown if the request could not be opened. I wanted to block the caller until the connection opened. Calling .Start() and having it throw an exception is much "cleaner" (in my mind at least) than calling .Start() then having it execute OK just to fire off an error delegate immediately.

>>I got both the synchronous and Asynchronous methods in my class when I get to using it in my newest hobby project I will be able to choose which best suits my needs.

If you carefully design an asynchronous code base for your twitter API you could easily convert it to synchronous on the surface by blocking calls until your async calls fire ;)

If you carefully design an asynchronous code base for your twitter API you could easily convert it to synchronous on the surface by blocking calls until your async calls fire

I developed it synchronously first just to get the twitter api calls right, then I just added extra methods to the class to handle it Asynchronously, and I'm really satisfied with that. Now I just have to extend the class to all the other API calls...

although I'm not sure the way I have started it is the best way to go about it, might have been better to have a twitter object that created child objects of each general subject from the API (user_timeline, Friends_timeline, Status, Update, ect) and put the code fore each different part in there, so that way using the code would be much more organized.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.