我需要调用第三方代码,可选择启动新线程,执行一些处理,然后在我的对象上调用不同的方法。我需要的是等待第三方处理完成,然后从原始方法返回。换句话说,我有一个这样的课程(C#):
class MyClass: IThirdPartyInterface {
void MyMethod() {
//some preprocessing
//call a 3rd party static method
ThirdParty.DoSomething(this);
}
void FinishedProcessing() {
//some postprocessing
//???
}
}
我想修改MyMethod,使其仅在DoSomething中启动的线程完成执行并调用FinishedProcessing方法后返回。由于线程是由第三方代码启动的,我无法访问它,所以我不能在这里使用Thread.Join。那么,我该怎么做呢?
答案 0 :(得分:3)
你需要使用System.Threading.AutoResetEvent,它会是这样的:
class MyClass: IThirdPartyInterface {
AutoResetEvent _event = new AutoResetEvent(false);
void MyMethod() {
ThirdParty.DoSomething(this);
_event.WaitOne();
}
void FinishedProcessing() {
_event.Set();
}
}
如果线程在第三方类调用FinishedProcessing方法后继续运行,则会有所不同:
class MyClass: IThirdPartyInterface {
AutoResetEvent _event = new AutoResetEvent(false);
Thread _thread;
void MyMethod() {
ThirdParty.DoSomething(this);
_event.WaitOne();
_thread.Join();
}
void FinishedProcessing() {
_thread = Thread.CurrentThread;
_event.Set();
}
}
答案 1 :(得分:0)
使你的MyMethod()异步,然后在自定义await方法中运行thirdparty方法,像这样出现:
private async void MyMethod()
{
var result = await WaitAsynchronouslyAsync();
}
public async Task<string> WaitAsynchronouslyAsync()
{
await ThirdParty.DoSomething(this);
return "Finished";
}
答案 2 :(得分:0)
如果ThirdParty.DoSomething不支持异步模式 你可以使用额外的代理与终结器。 但它可能会影响应用程序性能,如“while(myBoolFlag){}”。
class Program
{
static void Main(string[] args)
{
var list = new List<ManualResetEvent>();
for (var i = 0; i < 10000; i++)
{
var m = new ManualResetEvent(false);
list.Add(m);
new Thread(Start).Start(m);
if (i > 0 && (i % 10) == 0)
for (int j = i - 10; j < i; j++)
{
list[j].WaitOne(1000);// wait signal
GC.Collect(); //force finalizer
A.Print();
}
}
}
private static void Start(object obj)
{
new A(obj as ManualResetEvent, null);
}
}
public class A : IThirdPartyInterface
{
public static long time1;
public static long count1;
private DateTime start = DateTime.Now;
private ManualResetEvent _stop;
private IThirdPartyInterface _origin;
public A(ManualResetEvent stop, IThirdPartyInterface origin)
{
_stop = stop;
_origin = origin;
}
~A()
{
Interlocked.Increment(ref count1);
Interlocked.Add(ref time1, (long)(DateTime.Now - start).TotalMilliseconds);
_stop.Set(); //send signal
}
public static void Print()
{
Console.Write("\r" + A.time1 + "\\" + A.count1 + " ");
if (A.count1 != 0)
Console.Write((A.time1 / A.count1).ToString());
}
}