пятница, 4 января 2008 г.

Асинхронные делегаты (продолжение)

Рассмотрим более полный пример использования асинхронного делегата. Пусть делегат имеет не 1 параметер, передаваемый по значению, как в прошлом посте, а три. Первый пусть передается по значению, второй параметер имеет модификатор out, а третий - ref.

delegate string TestDelegate(string s, out string s1, ref string s2)

У BeginInvoke и EndInvoke появляются дополнительные параметры, которые необходимо учитывать.
BeginInvoke(string,out string, ref string, AsyncCallback, object);
EndInvoke(out string, ref string, IAsyncResult).

В EndInvoke первые 2 параметра позволяют получать значения, вычисляемые в делегате.

Код примера приведен ниже:
/**
У делегата появились 2 дополнительных параметра по отношению к предыдущему посту.
*/
delegate string TestDelegate(string s, out string s1, ref string s2);
class MainClass
{
private TestDelegate td;

/**
Функция, которая регистрируется нами, имеет 2 дополнительных параметра с модификаторами out и ref. В теле функции происходит задание значений для данных параметров.
*/
public string TestDelegateFunc(string s, out string s1, ref string s2)
{
Thread.Sleep(5000);
s1=string.Format("new s1 value: {0}",s);
s2=string.Format("new s2 value: {0}", s);
return string.Format("Result string: {0}",s);
}

/**
По отношению к предыдущему посту функция изменилась следующим образом:
Через EndInvoke появилась возможность получения 2-х дополнительных параметров,
которые соответсвуют параметрам делегата с модификаторами out и ref соответственно.
*/
public void ResultFunc(IAsyncResult ar)
{
StringBuilder sb=(StringBuilder) ar.AsyncState;
AsyncResult ar1=(AsyncResult)ar;
TestDelegate td1=(TestDelegate)ar1.AsyncDelegate;
string s1;
string s2="";
sb.Append(td1.EndInvoke(out s1, ref s2,ar));
Console.WriteLine("In Result Func: "+sb.ToString()+"; s1: "+s1+"; s2: "+s2);
}

private StringBuilder sb=new StringBuilder("Origin!");

/**
При вызове BeginInvoke появляются еще 2 параметра по отношению к предыдущему посту, которые имеею модификаторы out и ref соответственно.
*/
public void test()
{
td=new TestDelegate(TestDelegateFunc);
string s1;
string s2="";
td.BeginInvoke("Test String",out s1, ref s2, new AsyncCallback(ResultFunc),sb);
}

/**
Код не изменился по отношению к предыдущему посту
*/
public void atEnd()
{
Console.WriteLine("Result value: "+sb.ToString());
}

/**
Код остается без изменения по отношению к предыдущему посту
*/
public static void Main(string[] args)
{
MainClass mc=new MainClass();
mc.test();
Console.WriteLine("Before sleeping");
Thread.Sleep(10000);
Console.WriteLine("After sleeping");
mc.atEnd();
}
}

Комментариев нет: