Я пытаюсь повторно использовать некоторый код .NET, который выполняет некоторые вызовы для службы типа уровня доступа к данным. Мне удалось упаковать как входные данные для метода, так и выходные данные метода, но, к сожалению, служба вызывается из внутреннего кода, который я действительно не хочу переписывать, чтобы он был асинхронным.
К сожалению, код веб-службы, сгенерированный в Silverlight, производит только асинхронные методы, поэтому мне было интересно, есть ли у кого-нибудь работающий код, которому удалось обойти это?
Примечание : мне не нужно выполнять основной путь кода здесь в потоке пользовательского интерфейса, но рассматриваемый код будет ожидать, что вызовы, которые он делает к уровням доступа к данным, являются синхронными по своей природе, но вся работа может выполняться в основном в фоновом потоке.
Я попробовал рецепт, найденный здесь: Простой способ синхронного вызова служб WCF в Silverlight , но, к сожалению, он истекает и никогда не завершает вызов.
Или, скорее всего, происходит то, что вызывается обработчик завершенных событий, но только после возврата метода. Я подозреваю, что обработчик событий вызывается из диспетчера или аналогичного, и, поскольку я блокирую основной поток здесь, он никогда не завершится, пока код фактически не вернется в цикл GUI.
Или что-то в этом роде.
Вот моя собственная версия, которую я написал до того, как нашел вышеуказанный рецепт, но она страдает от той же проблемы:
public static object ExecuteRequestOnServer(Type dalInterfaceType, string methodName, object[] arguments)
{
string securityToken = "DUMMYTOKEN";
string input = "DUMMYINPUT";
object result = null;
Exception resultException = null;
object evtLock = new object();
var evt = new System.Threading.ManualResetEvent(false);
try
{
var client = new MinGatServices.DataAccessLayerServiceSoapClient();
client.ExecuteRequestCompleted += (s, e) =>
{
resultException = e.Error;
result = e.Result;
lock (evtLock)
{
if (evt != null)
evt.Set();
}
};
client.ExecuteRequestAsync(securityToken, input);
try
{
var didComplete = evt.WaitOne(10000);
if (!didComplete)
throw new TimeoutException("A data access layer web service request timed out (" + dalInterfaceType.Name + "." + methodName + ")");
}
finally
{
client.CloseAsync();
}
}
finally
{
lock (evtLock)
{
evt.Close();
evt = null;
}
}
if (resultException != null)
throw resultException;
else
return result;
}
По сути, оба рецепта делают это:
- Настройка ManualResetEvent
- Подключиться к завершенному событию
- Обработчик событий получает результат от сервисного вызова и сигнализирует о событии
- Основной поток теперь запускает вызов веб-службы асинхронно
- Затем он ожидает события, чтобы стать сигнальным
Однако обработчик событий не вызывается до тех пор, пока не будет возвращен указанный выше метод, поэтому мой код проверяет наличие evt != null
и т. Д., Чтобы исключить TargetInvocationException от уничтожения моей программы после истечения времени ожидания метода.
Кто-нибудь знает:
- ... если это вообще возможно в Silverlight 3
- ... что я не так сделал выше?