9

从概念上讲,我想完成以下任务,但在理解如何在 C# 中正确编码时遇到了麻烦:


SomeMethod { // Member of AClass{}
    DoSomething;
    Start WorkerMethod() from BClass in another thread;
    DoSomethingElse;
}

然后,当 WorkerMethod() 完成时,运行:


void SomeOtherMethod()  // Also member of AClass{}
{ ... }

任何人都可以举个例子吗?

4

7 回答 7

13

BackgroundWorker类被添加到 .NET 2.0 正是为了这个目的。

简而言之,您可以:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate { myBClass.DoHardWork(); }
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SomeOtherMethod);
worker.RunWorkerAsync();

如果需要,您还可以添加花哨的东西,例如取消和进度报告 :)

于 2008-09-16T17:41:52.870 回答
5

在 .Net 2 中引入了 BackgroundWorker,这使得运行异步操作变得非常容易:

BackgroundWorker bw = new BackgroundWorker { WorkerReportsProgress = true };

bw.DoWork += (sender, e) => 
   {
       //what happens here must not touch the form
       //as it's in a different thread
   };

bw.ProgressChanged += ( sender, e ) =>
   {
       //update progress bars here
   };

bw.RunWorkerCompleted += (sender, e) => 
   {
       //now you're back in the UI thread you can update the form
       //remember to dispose of bw now
   };

worker.RunWorkerAsync();

在 .Net 1 中,您必须使用线程。

于 2008-09-16T19:01:24.833 回答
2

您必须使用 AsyncCallBacks。您可以使用 AsyncCallBacks 指定方法的委托,然后指定在目标方法执行完成后调用的 CallBack 方法。

这是一个小示例,您自己运行并查看它。

类程序{

    public delegate void AsyncMethodCaller();


    public static void WorkerMethod()
    {
        Console.WriteLine("I am the first method that is called.");
        Thread.Sleep(5000);
        Console.WriteLine("Exiting from WorkerMethod.");
    }

    public static void SomeOtherMethod(IAsyncResult result)
    {
        Console.WriteLine("I am called after the Worker Method completes.");
    }



    static void Main(string[] args)
    {
        AsyncMethodCaller asyncCaller = new AsyncMethodCaller(WorkerMethod);
        AsyncCallback callBack = new AsyncCallback(SomeOtherMethod);
        IAsyncResult result = asyncCaller.BeginInvoke(callBack, null);
        Console.WriteLine("Worker method has been called.");
        Console.WriteLine("Waiting for all invocations to complete.");
        Console.Read();

    }
}
于 2008-09-16T18:34:45.973 回答
2

虽然这里有几种可能性,但我会使用委托,异步调用 usingBeginInvoke方法。

警告:不要忘记始终调用EndInvokeIAsyncResult避免最终的内存泄漏,如本文所述

于 2008-09-16T21:08:07.117 回答
1

查看 BackgroundWorker。

于 2008-09-16T17:39:33.033 回答
1

使用异步委托:

// Method that does the real work
public int SomeMethod(int someInput)
{
Thread.Sleep(20);
Console.WriteLine(”Processed input : {0}”,someInput);
return someInput+1;
} 


// Method that will be called after work is complete
public void EndSomeOtherMethod(IAsyncResult result)
{
SomeMethodDelegate myDelegate = result.AsyncState as SomeMethodDelegate;
// obtain the result
int resultVal = myDelegate.EndInvoke(result);
Console.WriteLine(”Returned output : {0}”,resultVal);
}

// Define a delegate
delegate int SomeMethodDelegate(int someInput);
SomeMethodDelegate someMethodDelegate = SomeMethod;

// Call the method that does the real work
// Give the method name that must be called once the work is completed.
someMethodDelegate.BeginInvoke(10, // Input parameter to SomeMethod()
EndSomeOtherMethod, // Callback Method
someMethodDelegate); // AsyncState
于 2008-09-16T18:03:29.823 回答
0

好的,我不确定你想怎么做。从您的示例中,看起来 WorkerMethod 没有创建自己的线程来执行,但您想在另一个线程上调用该方法。

在这种情况下,创建一个调用 WorkerMethod 然后调用 SomeOtherMethod 的短工作方法,并将该方法排队到另一个线程上。然后当 WorkerMethod 完成时, SomeOtherMethod 被调用。例如:

public class AClass
{
    public void SomeMethod()
    {
        DoSomething();

        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            BClass.WorkerMethod();
            SomeOtherMethod();
        });

        DoSomethingElse();
    }

    private void SomeOtherMethod()
    {
        // handle the fact that WorkerMethod has completed. 
        // Note that this is called on the Worker Thread, not
        // the main thread.
    }
}
于 2008-09-16T17:52:48.977 回答