Async Delegate EndInvoke 比预期更早终止循环
Async Delegate EndInvoke terminating loop earlier than expected
我是 运行 斐波那契方法上的委托异步回调模式。这个静态方法包含一个循环,其中线程休眠 300ms 以打印出后台线程池 Id。不幸的是,在我的 FibCompleted() 中,EndInvoke 方法正在终止我的进程。任何提示都会有所帮助。
谢谢。
public delegate int FibPointer(int x); // FibbonaciSequence() pointer
class Program
{
static void Main(string[] args)
{
// fibonacci Length
int fibLength = 8;
// point delegate to method
FibPointer fb = new FibPointer(FibonacciSequence);
IAsyncResult iftAR = fb.BeginInvoke(
fibLen, new AsyncCallback(FibCompleted), null);
Console.WriteLine("Fibonacci process now running on thread {0}\n",
Thread.CurrentThread.ManagedThreadId);
int count = 0;
while (!iftAR.IsCompleted) // completion occurs when userIN length is reached
{
// run fib sequence.
Console.WriteLine("{0}", FibonacciSequence(count));
count++;
}
Console.ReadKey();
}
static int FibonacciSequence(int num)
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
}
static void FibCompleted(IAsyncResult ar)
{
Console.WriteLine("\nFib Sequence Completed.");
// retrieve result
AsyncResult res = (AsyncResult)ar;
//FibPointer fp = ar.AsyncState as FibPointer;
FibPointer fp = res.AsyncDelegate as FibPointer;
// call EndInvoke to grab results
string returnVal = fp.EndInvoke(ar).ToString();
Console.WriteLine("\nreturn val is: {0}", returnVal);
}
}
如果必须使用纯APM。这是一个实际的例子。
void Main()
{
// fibonacci Length
int fibLength = 8;
// point delegate to method
Func<int, int> fb = FibonacciSequence;
var completedEvent = new System.Threading.AutoResetEvent(false);
var iftAR = fb.BeginInvoke(fibLength, FibCompleted, completedEvent);
completedEvent.WaitOne();
var result = fb.EndInvoke(iftAR);
Console.WriteLine("Fibonacci process now running on thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
}
static int FibonacciSequence(int num)
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
}
static void FibCompleted(IAsyncResult ar)
{
var completedEvent = (AutoResetEvent)ar.AsyncState;
completedEvent.Set();
}
不过。没有人再使用纯 APM。 APM 被 EAP 取代,EAP 又被 TAP 取代。
我建议你改学 TAP。它要简单得多。要使 APM 代码适应 TAP,您可以使用 TaskFactory 辅助函数。
async Task Main()
{
// fibonacci Length
int fibLength = 8;
// point delegate to method
Func<int, int> fb = FibonacciSequence;
var result = await Task.Factory.FromAsync (fb.BeginInvoke, fb.EndInvoke, fibLength, null);
Console.WriteLine("Fibonacci process now running on thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
}
static int FibonacciSequence(int num)
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
}
然而,大多数人只会在 TAP 工作。看起来像这样。
async Task Main()
{
// fibonacci Length
int fibLength = 8;
var result = await FibonacciSequence(fibLength);
Console.WriteLine("Fibonacci process now running on thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
}
static Task<int> FibonacciSequence(int num)
{
// Run computationally intensive work on thread pool.
return Task.Run(() =>
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
});
}
我是 运行 斐波那契方法上的委托异步回调模式。这个静态方法包含一个循环,其中线程休眠 300ms 以打印出后台线程池 Id。不幸的是,在我的 FibCompleted() 中,EndInvoke 方法正在终止我的进程。任何提示都会有所帮助。 谢谢。
public delegate int FibPointer(int x); // FibbonaciSequence() pointer
class Program
{
static void Main(string[] args)
{
// fibonacci Length
int fibLength = 8;
// point delegate to method
FibPointer fb = new FibPointer(FibonacciSequence);
IAsyncResult iftAR = fb.BeginInvoke(
fibLen, new AsyncCallback(FibCompleted), null);
Console.WriteLine("Fibonacci process now running on thread {0}\n",
Thread.CurrentThread.ManagedThreadId);
int count = 0;
while (!iftAR.IsCompleted) // completion occurs when userIN length is reached
{
// run fib sequence.
Console.WriteLine("{0}", FibonacciSequence(count));
count++;
}
Console.ReadKey();
}
static int FibonacciSequence(int num)
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
}
static void FibCompleted(IAsyncResult ar)
{
Console.WriteLine("\nFib Sequence Completed.");
// retrieve result
AsyncResult res = (AsyncResult)ar;
//FibPointer fp = ar.AsyncState as FibPointer;
FibPointer fp = res.AsyncDelegate as FibPointer;
// call EndInvoke to grab results
string returnVal = fp.EndInvoke(ar).ToString();
Console.WriteLine("\nreturn val is: {0}", returnVal);
}
}
如果必须使用纯APM。这是一个实际的例子。
void Main()
{
// fibonacci Length
int fibLength = 8;
// point delegate to method
Func<int, int> fb = FibonacciSequence;
var completedEvent = new System.Threading.AutoResetEvent(false);
var iftAR = fb.BeginInvoke(fibLength, FibCompleted, completedEvent);
completedEvent.WaitOne();
var result = fb.EndInvoke(iftAR);
Console.WriteLine("Fibonacci process now running on thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
}
static int FibonacciSequence(int num)
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
}
static void FibCompleted(IAsyncResult ar)
{
var completedEvent = (AutoResetEvent)ar.AsyncState;
completedEvent.Set();
}
不过。没有人再使用纯 APM。 APM 被 EAP 取代,EAP 又被 TAP 取代。
我建议你改学 TAP。它要简单得多。要使 APM 代码适应 TAP,您可以使用 TaskFactory 辅助函数。
async Task Main()
{
// fibonacci Length
int fibLength = 8;
// point delegate to method
Func<int, int> fb = FibonacciSequence;
var result = await Task.Factory.FromAsync (fb.BeginInvoke, fb.EndInvoke, fibLength, null);
Console.WriteLine("Fibonacci process now running on thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
}
static int FibonacciSequence(int num)
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
}
然而,大多数人只会在 TAP 工作。看起来像这样。
async Task Main()
{
// fibonacci Length
int fibLength = 8;
var result = await FibonacciSequence(fibLength);
Console.WriteLine("Fibonacci process now running on thread {0}\n", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(result);
}
static Task<int> FibonacciSequence(int num)
{
// Run computationally intensive work on thread pool.
return Task.Run(() =>
{
int num1 = 0, num2 = 1, res = 0;
if (num == 0) return 0;
if (num == 1) return 1;
for (int i = 0; i < num; i++)
{
res = num1 + num2;
num1 = num2;
num2 = res;
Thread.Sleep(300);
// track background thread from pool
Console.WriteLine("Working on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}
return res;
});
}