Ну, я не мог проигнорировать совет, который я видел везде, что если я не буду вызывать EndInvoke, я МОГУТ утратить некоторые ресурсы, поэтому мне нужно было попытаться заснуть это ночью и не волноваться, что я был приближается к утесу.
Решение, которое я нашел, использовало функцию асинхронного обратного вызова. Если звонок вернулся вовремя, я вызываю EndInvoke там. Если нет, я продолжаю щелкать по кнопке и позволяю асинхронной функции обратного вызова убирать беспорядок с EndInvoke.
Чтобы ответить на мой собственный вопрос о веб-приложении и «будет ли кто-нибудь, кто будет слушать после того, как я перестану работать и двигаться дальше», я обнаружил, что они будут - даже если бы я остановился и перешел, если я смотрел более поздний вывод , этот асинхронный вызов вернет и запустит функцию обратного вызова, даже если я уже вернул вывод клиенту.
Я использовал кое-что из того, что нашел по адресу: http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx
... а также в сочетании с вещами обратного вызова, которые я нашел в другом месте. Вот небольшая примерная функция того, что я сделал ниже. Он сочетает в себе то, что я нашел в Спасибо за вклад каждого!
public class RemotePaymentProcessor
{
string currentResponse = string.Empty;
private delegate string SendProcessPaymentDelegate(string creditCardNumber);
private string SendProcessPayment(string creditCardNumber)
{
SlowResponseService.SlowResponseService srs = new WebServiceTimeout.SlowResponseService.SlowResponseService();
string response = srs.GetSlowResponse(creditCardNumber);
return response;
}
public string ProcessPayment(string creditCardNumber, int timeoutMilliseconds)
{
string response = string.Empty;
SendProcessPaymentDelegate sppd = new SendProcessPaymentDelegate(SendProcessPayment);
IAsyncResult ar = sppd.BeginInvoke(creditCardNumber, new AsyncCallback(TransactionReturned), sppd);
if (!ar.AsyncWaitHandle.WaitOne(timeoutMilliseconds, false))
{
// Async call did not return before timeout
response = "TIMEOUT";
}
else
{
// Async call has returned - get response
response = sppd.EndInvoke(ar);
}
currentResponse = response; // Set class variable
return response;
}
private void TransactionReturned(IAsyncResult ar)
{
string response = string.Empty;
// Get delegate back out of Async object
SendProcessPaymentDelegate sppd = (SendProcessPaymentDelegate)ar.AsyncState;
// Check outer class response status to see if call has already timed out
if(currentResponse.ToUpper().Equals("TIMEOUT"))
{
// EndInvoke has not yet been called so call it here, but do nothing with result
response = sppd.EndInvoke(ar);
}
else
{
// Transaction must have returned on time and EndInvoke has already been called. Do nothing.
}
}
}