Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:
• internal IMessage _replyMsg
В случае синхронного вызова результат отправляется вызывающей стороне опять же в форме сообщения. Данное поле будет хранить ссылку на это сообщение по завершении вызова.
• internal Context _ctx
Домен синхронизации может состоять из нескольких контекстов, и только один из них содержит свойство синхронизации данного домена. С каждым контекстом связана своя цепочка перехватчиков. В каждой такой цепочке имеется перехватчик, ассоциированный со свойством синхронизации. Вызов, перемещающийся
• internal LogicalCallContext _callCtx
Условия выполнения вызова определяются не только контекстом, в котором он должен выполняться, но и контекстом логического вызова, сопровождающим данный вызов. Подробнее это понятие будет объяснено далее. Поле _callctx хранит ссылку на контекст логического вызова для данного вызова.
Немного про асинхронные вызовы
При разборе кода атрибута синхронизации нам придется часто упоминать такое понятие как асинхронный вызов. Уместно сделать отступление и разобрать код, демонстрирующий работу с асинхронными вызовами.
Рассмотрим следующую ситуацию. Сервер предоставляет услуги по проведению сложных математических вычислений, требующих значительных временных затрат.
При использовании синхронных вызовов клиент должен был бы последовательно вызывать необходимые методы. При этом при каждом синхронном вызове клиент блокируется до получения ответа, что не дает ему возможность вызывать методы сервера параллельно и выполнять какую-либо другую полезную работу во время ожидания результатов от сервера.
При использовании асинхронных вызовов клиент может вызывать методы сервера параллельно и в процессе ожидания выполнять дополнительную работу.
В данном случае услуги, предоставляемые сервером, сводятся к выполнению двух арифметических операций (сложение и умножение на 2). Работа, которую клиент выполняет в ожидании ответов от сервера, состоит в выводе на консоль отметок о завершении очередного 100 mс временного интервала.
using System;
using System.Threading;
using System.Runtime.Remoting;
public class Server {
public static bool Sum(int x, int y, out int z) {
Console.WriteLine(
"Server (Sum method) thread = " +
Thread.CurrentThread.GetHashCode+
"; PoolThread = "+
Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(1000);
z = 0;
try {
z = checked((int)(x + y));
}
catch (Exception) {
return false;
}
return true;
}
public static bool MultBy2(int x, out int y) {
Console.WriteLine {
"Server (MultBy2 method) thread = " +
Thread.CurrentThread.GetHasheode+
"; PoolThread = "+
Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(1000);
y = 0;
try {
у = checked((int) (x*2));
}
catch (Exception) {
return false;
}
return true;
}
}
Public class Client {
private static int workCount = 0;
private delegate bool HardFunction2Args (
int x, int y, out int result);
private delegate bool HardFunctionlArg (
int x, out int result);
private static void SumCallback(IAsyncResult ar) {
int z;
HardFunction2Args sum =
(HardFunction2Args)ar.AsyncState;
bool result = sum.Endlnvoke(out z, ar);
if (result) Console.WriteLine (
"SumCallback: Sum = " + z);
else Console.WriteLine (
"SumCallback: Bad arguments for Server.Sum
workCount++;
}
private static void MultCallback(IAsyncResult ar) {
int z;
HardFunctionlArg mult =
(HardFunctionlArg)ar.AsyncState;
bool result = mult.Endlnvoke(out z, ar);
if (result) Console.WriteLine (
"MultCallback: MultBy2 = " + z);
else Console.WriteLine (
"MultCallback: Bad argument for MultBy2");
workCount++;
}
public static void Main {
int sumResult, multResult, count = 0;
Console.WriteLine("Client thread = " +
Thread.CurrentThread.GetHashCode + PoolThread = "+
Thread.CurrentThread.IsThreadPoolThread);
HardFunction2Args sum =
new HardFunction2Args(Server.Sum);
HardFunctionlArg mult =
new HardFunctionlArg(Server.MultBy2);
AsyncCallback sumCallback =
new AsyncCallback(SumCallback);
AsyncCallback multCallback =
new AsyncCallback(MultCallback);
IAsyncResult arSum = sum.Beginlnvoke(3, 4,
out sumResult, sumCallback, sum);
IAsyncResult arMult = mult.Beginlnvoke(5,
out multResult, multCallback, mult);
while (workCount < 2) {
Console.WriteLine("Client thread: count = "+ count++);
Thread.Sleep(100);
}
Console.WriteLine("Bye!");