Позвольте мне дать вам этот пример кода, чтобы прояснить ситуацию.Пожалуйста, создайте новое консольное приложение и используйте это
public class Test
{
private int WorkerFunction(string a, string b)
{
//this is the guy that is supposed to do the long running work
Console.WriteLine(a);
Console.WriteLine(b);
return a.Length + b.Length;
}
private void MyCallBack(IAsyncResult ar)
{
Func<string, string, int> function = ar.AsyncState as Func<string, string, int>;
int result = function.EndInvoke(ar);
Console.WriteLine("Result is {0}", result);
}
public void CallMethod()
{
Func<string, string, int> function = new Func<string, string, int>(WorkerFunction);
IAsyncResult result = function.BeginInvoke("param1", "param2", MyCallBack, function);
}
}
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.CallMethod();
}
}
. Как вы видите, функция обратного вызова (MyCallBack) получает объект IAsyncResult, переданный обратно ему.Именно этот объект IAsynchResult AyncState дает вам исходный объект, который вы передали в вызове метода BeginInvoke.В этом случае (и в качестве общей практики) вы передаете сам делегат как объект (который был переменной с именем «функция»).После того, как был вызван обратный вызов, я затем вернул исходный объект делегата, запросив ar.AsyncState, затем вызвал EndInvoke, чтобы вернуть результат.
Что касается точки останова, которая не была достигнута, я боюсьМне нужно больше информации об этом.Что именно ты имеешь ввиду?Где этот оператор Console.WriteLine?
НОВЫЙ ОТВЕТ. Хорошо, вот моя версия вашего кода.По сути, независимо от того, откуда вы вызываете EndInvoke, вам нужно вызывать его для фактического объекта делегата (в вашем случае переменная «function», которую вы создаете, передает ей фактический объект IAsyncResult).Код, который у вас есть, пытается замаскировать эту возможность, но я должен сказать, что есть менее сложные способы сделать это.Я буду более чем рад написать для вас какую-нибудь обертку, если хотите.Сейчас я просто возвращаю вам ваш код с моим небольшим дополнением, которое должно заставить его работать.Поскольку вы используете переменные уровня класса, следовательно, я вынужден использовать один из них сам.На данный момент это не совсем потокобезопасно.Но здесь идет
using System;
using System.Collections.Generic;
using System.Text;
namespace TestAsync
{
class Program
{
private static Wrapper test = new Wrapper();
static void Main(string[] args)
{
var objectState = new object();
test.BeginMethod("parameter 1", "parameter 2", Callback, objectState);
Console.ReadKey();
}
private static void Callback(IAsyncResult ar)
{
string result = test.EndMethod(ar);
Console.WriteLine(result);
}
}
public interface ITest
{
IAsyncResult BeginMethod(string s1, string s2, AsyncCallback cb, object state);
string EndMethod(IAsyncResult result);
}
public class Wrapper
{
private ITest proxy = new Test();
public void BeginMethod(string s1, string s2, AsyncCallback cb)
{
proxy.BeginMethod(s1, s2, cb, proxy);
}
public string EndMethod(IAsyncResult result)
{
return ((ITest)(result.AsyncState)).EndMethod(result);
}
}
public class Test : ITest
{
Func<string, string, string> _delgateObject;
private string WorkerFunction(string a, string b)
{
// "long running work"
return a + "|" + b;
}
public IAsyncResult BeginMethod(string s1, string s2, AsyncCallback cb, object state)
{
Func<string, string, string> function = new Func<string, string, string>(WorkerFunction);
this._delgateObject = function;
IAsyncResult result = function.BeginInvoke(s1, s2, cb, state);
return result;
}
public string EndMethod(IAsyncResult result)
{
var test = result.AsyncState;
return this._delgateObject.EndInvoke(result);
}
}
public delegate TResult Func<T1, T2, TResult>(T1 t1, T2 t2);
}