开发者

Executing on a background thread using BeginInvoke

开发者 https://www.devze.com 2023-01-19 09:38 出处:网络
I\'m trying out multithreading but I cant figure out why the the piece of code below blocks the UI when task.Execute() is called?

I'm trying out multithreading but I cant figure out why the the piece of code below blocks the UI when task.Execute() is called?

public class Task<TRes>
{
    private Func<TRes> _func;
    public Task(Func<TRes> func)
    {
        _func = func;
    }
    public TRes Execute()
    {
        var iasync = _func.BeginInvoke(null, null);
        return _func.EndInvoke(iasync);
    }
}

I'm not trying to solve any problem in particular. Just wondering why the UI blocks when it hits Thread.Sleep even though the current thread (the one that was put to "sleep") is a ThreadPool t开发者_C百科hread (and not the main UI thread). Below is a button click event that uses the Task class.

 var task = new Task<string>(() =>
            {
                var start = DateTime.Now;
                var isBackGround = Thread.CurrentThread.IsBackground ;
                var isThreadPool = Thread.CurrentThread.IsBackground;

                Thread.Sleep(5000);
                return String.Format("Start {0} : End {1}", start, DateTime.Now);
            }
          );
        this.label1.Text = task.Execute();


The problem is that calling EndInvoke blocks the calling thread until the function finishes executing. What you're doing is spawning a worker thread to execute your _func and then blocking until that worker finishes. I would recommend using the callback parameter of BeginInvoke. And if you're doing GUI stuff, don't forget about Dispatcher.

Come to think of it, I wouldn't recommend starting multithreading with GUIs at all, since it can be a real pain. Start off with console applications so you can get the hang of the whole multithreading thing, then move to GUIs, where things can get painful.

void Main()
{
    var cookies = new IAsyncResult[10];
    Action action = delegate
    {
        // I'm going to print out a bunch of numbers here
        for (int i = 0; i < 100; ++i)
            Console.WriteLine(i);
    }

    for (int i = 0; i < cookies.Length; ++i)
        cookies[i] = action.BeginInvoke(null, null);

    // with all 10 threads executing, you'll see numbers print out in some crazy,
    // unpredictable order...this line will come out somewhere in the mess (or maybe
    // before it...who knows?)
    Console.WriteLine("All threads started!");

    // we wait for each of the workers to finish executing here:
    foreach (var c in cookies)
        action.EndInvoke(c);

    // and this will always be printed last, thereby demonstrating that EndInvoke
    // causes the calling thread to wait for the action to finish
    Console.WriteLine("Done!");
}


I know that this does't directly answer your question, but I just wanted to point you towards the System.Threading.Tasks namespace, if you are using .Net 4.0. The Task(of T) is really well documented and performs as expected.

-Josh

0

精彩评论

暂无评论...
验证码 换一张
取 消