Что лучший способ состоит в том, чтобы отменить асинхронный запрос WCF?

(Принятие метода WCF под названием "MyFunction")

В настоящее время, для поддержки отмены запроса WCF я использую методы BeginMyFunction/EndMyFunction, сгенерированные svcutil (и обрабатываю флаг isCanceled при диспетчеризации результатов основному потоку). Я хотел бы использовать метод MyFunctionAsync (и сцепляющийся в событие MyFunctionAsyncCompleted вместо этого) для асинхронных вызовов вместо Начинают/Заканчивают.

Что является лучшим/поддерживаемым способом обработать отмену запросы WCF при использовании MyFunctionAsyncCompleted и все еще обеспечении, что событие не становится стреляемым страница, это больше не загружалось (т.е. навигация страницы в кадре).

Спасибо!

Править:

Я решил, что хочу создать свой объект WcfClient на основе на вызов (в противоположность per-WPF-Page или на приложение), таким образом, вот то, что я придумал:

public void StartValidation(){
    WcfClient wcf = new WcfClient();
    wcf.IsValidCompleted += new EventHandler<IsValidCompletedEventArgs>(wcf_IsValidCompleted);
    //pass the WcfClient object as the userState parameter so it can be closed later
    wcf.IsValidAsync(TextBox.Text, wcf);  
}

void wcf_IsValidCompleted(object sender, IsValidCompletedEventArgs e) {
    if(!m_IsCanceled){
        //Update the UI
        //m_IsCanceled is set to true when the page unload event is fired
    }
    //Close the connection
    if (e.UserState is WcfClient) {
        ((WcfClient)e.UserState).Close();
    }
}

Я нахожу трудным выяснить, каково рекомендуемый способ выполнить то, что я только что реализовал. Прекрасен это как есть или там ловушки/пограничные случаи, о которых я должен волноваться? Что золотой является стандартным когда дело доходит до надлежащей отмены вызова WCF?

9
задан Mark Carpenter 17 June 2010 в 16:04
поделиться

3 ответа

Не существует способа отменить асинхронный запрос, если вы не создадите асинхронные функции вручную. Учитывая, что Вы автоматически генерируете свои вызовы WCF, это сделало бы это больше из рутины. Даже тогда, как вы сказали, вызов не отменяется, он все еще будет выполнять свой курс. Если вы все еще хотите иметь отмену вы просто должны убедиться, что клиент/UI игнорирует результаты от вызова.

7
ответ дан 4 December 2019 в 07:47
поделиться

Отмена запроса нецелесообразна в общем смысле просто из-за асинхронного характера запроса, о котором вы говорите. Могут быть выполнены конкретные обходные пути. Например, добавление нового сигнала отмены в ваш протокол, который устанавливает некоторое общее состояние, которое ваша основная длительная задача периодически проверяет, чтобы убедиться, что она должна продолжать выполнение.

В любом случае, опять же из-за асинхронного характера запроса, я считаю, что ответственность за игнорирование результатов отмененного запроса по-прежнему лежит на клиенте. Невозможно гарантировать, что клиент не получит ответ на запрос, который был отменен просто потому, что между клиентом и сервером существует гонка. Можно добавить дополнительный уровень, который отслеживает, было ли что-то отменено, и знает, что нужно отбросить ответ на запрос, но это не препятствует передаче результата клиенту.

2
ответ дан 4 December 2019 в 07:47
поделиться

Если я правильно вас понял, вы пытаетесь правильно прервать ожидающий вызов службы WCF. Вы хотите использовать событие MyFunctionCompleted , потому что оно обрабатывается в потоке пользовательского интерфейса.

Что вам, вероятно, следует сделать, так это вызвать метод Abort для WcfClient (вам необходимо сохранить ссылку на него). Это очистит ресурсы на стороне клиента. Сервер все равно завершит запрос, но клиент больше не будет его ждать. Вскоре после запуска события MyFunctionCompleted . Проверяя client.State , вы узнаете, был ли вызов успешным, неудачным или прерванным.

Вот небольшое тестовое приложение с кнопкой «Отправить», кнопкой «Прервать» и текстовым полем для результатов:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    private SomeServiceClient m_client;

    private void buttonSend_Click(object sender, EventArgs e)
    {
        m_client = new SomeServiceClient();
        m_client.MyFunctionCompleted += new EventHandler<MyFunctionCompletedEventArgs>(client_MyFunctionCompleted);
        m_client.MyFunctionAsync(4000, m_client);
    }

    private void buttonAbout_Click(object sender, EventArgs e)
    {
        if( m_client != null ) 
            m_client.Abort();
    }

    void client_MyFunctionCompleted(object sender, MyFunctionCompletedEventArgs e)
    {

        var client = e.UserState as SomeServiceClient;
        if (client != null)
        {
            if (client.State == System.ServiceModel.CommunicationState.Opened)
            {
                textBox.Text += string.Format("Result: {0}\r\n", e.Result);
                client.Close();
                return;
            }
            else if (client.State == System.ServiceModel.CommunicationState.Faulted)
            {
                textBox.Text += string.Format("Error: {0}\r\n", e.Error.Message);
            }
            client.Abort();
        }
    }
}

Нет обработки исключений и очистки ... Я не знаю, рекомендуется ли это, но я думаю, что вызов abort - правильный путь. Вам нужно каким-либо образом обрабатывать различные ситуации с ошибками.

1
ответ дан 4 December 2019 в 07:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: