Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call method in separate thread

I need to call class method in separate thread. The method has a parameter and a return value.

Details

I have a Form with two TextBoxes. User put value in the first TextBox and get the result in the second one:

 private void tbWord_TextChanged(object sender, TextChangedEventArgs e)
 {
     tbResponce.Text = Wiki.DoWork(tbWord.Text);
 }

The Wiki-class must use Wikipedia API:

public class Wiki
{
    private class State
    {
        public EventWaitHandle eventWaitHandle = new ManualResetEvent(false);
        public String result;
        public String word;
    }

    private static void PerformUserWorkItem( Object stateObject )
    {
        State state = stateObject as State;

        if(state != null)
        {
            Uri address = new Uri("http://en.wikipedia.org/w/api.php?action=opensearch&search=" + state.word);
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
            HttpWebResponse responce = (HttpWebResponse)request.GetResponse();

            StreamReader myStreamReader = new StreamReader(responce.GetResponseStream(), Encoding.GetEncoding(1251));
            state.result = myStreamReader.ReadToEnd();

            state.eventWaitHandle.Set(); 
        }
    }

    public static String DoWork(String _word)
    {
        State state = new State();
        state.word = _word;

        ThreadPool.QueueUserWorkItem(PerformUserWorkItem, state);
        state.eventWaitHandle.WaitOne();
        return state.result;                   
    }     
}

Problem

When user press keys in the tbWord the main form freeze and wait while Wiki class do all the work.

How can I run DoWork asynchronously?

like image 592
ceth Avatar asked Dec 09 '22 02:12

ceth


2 Answers

Or use TPL like this:

private void tbWord_TextChanged(object sender, TextChangedEventArgs e) 
 { 
    Task.Factory.StartNew(() =>
    {
        return Wiki.DoWrok(tbWord.Text);
    }).ContinueWith(taskState =>
    {
        tbResponce.Text = taskState.Result;
    }, TaskScheduler.FromCurrentSynchronizationContext());
 } 

see: http://msdn.microsoft.com/en-us/library/dd997394.aspx

like image 182
Polity Avatar answered Dec 25 '22 08:12

Polity


Look into using the BackgroundWorker class. This will allow you to run your operation asynchronously. You can then update your UI back on the Dispatcher thread when you get notified by the BackgroundWorker that it has completed the operation.

like image 37
Samuel Slade Avatar answered Dec 25 '22 09:12

Samuel Slade