正确中止或取消 PostAsync

Posted

技术标签:

【中文标题】正确中止或取消 PostAsync【英文标题】:Properly Abort or Cancel PostAsync 【发布时间】:2014-05-28 19:58:31 【问题描述】:

在使用 HttpClient 时是否有保证取消帖子的方法?我目前有一个调用 postAsync ,我试图使用 cancelToken 取消它,但它似乎实际上并没有中止/停止操作。我仍然可以看到我上传的图片已正确发布。

我在这里做错了什么,还是 HttpClient 可能在上传之后才处理取消令牌?

var sc = new StreamContent(uploadFile.Data);
content.Add(sc, uploadFile.FieldName, uploadFile.FileName);

var request = new HttpRequestMessage

    RequestUri = new Uri(ApiImageUrlUpload),
    Content = content
;

request.Headers.TryAddWithoutValidation("User-Agent", _sessionManager.UserAgent);
request.Headers.TransferEncodingChunked = true;

using(cancellationToken.Register(() => httpClient.CancelPendingRequests()))
    httpResponse = await HttpClient.PostAsync(new Uri(ApiImageUrlUpload), content, cancellationToken);

【问题讨论】:

相关:Cancel an 'HttpClient' POST request 该相关问题没有与 HTTP 相关的答案。 【参考方案1】:

您可以手动处理请求对象,该对象应抛出 ObjectDisposedException 并取消任何网络活动。

【讨论】:

Dispose 是否因为 GC 而不是真正的高性能?【参考方案2】:

试试这个代码示例

public partial class LoginForm : MaterialForm
    
        static NLog.Logger logger = LogManager.GetLogger("LoginForm");
        HttpClient client;
        HttpResponseMessage response;

        public LoginForm()
        
            InitializeComponent();

            materialLabelErrMessage.Visible = false;
        

        #region GUI events
        private void BntCancel_Click(object sender, EventArgs e)
        
            CancelLogin();
            Close();
        

        private void BtnOK_Click(object sender, EventArgs e)
        
            Login();
        

        private void TextBoxPassword_KeyDown(object sender, KeyEventArgs e)
        
            if (e.KeyCode == Keys.Enter)
            
                Login();
            

        

        private void TextBoxUsername_KeyDown(object sender, KeyEventArgs e)
        
            if (e.KeyCode == Keys.Enter)
            
                Login();
            
        

        #endregion

        #region Keyboard Helpers
        protected override bool ProcessDialogKey(Keys keyData)
        
            if (Form.ModifierKeys == Keys.None && keyData == Keys.Escape)
            
                CancelLogin();
                Close();
                return true;
            
            return base.ProcessDialogKey(keyData);
        
        #endregion

        async void Login()
        
            try
            
                pbLogin.Visible = true;
                btnOK.Enabled = false;

                materialLabelErrMessage.Text = string.Empty;
                materialLabelErrMessage.Visible = false;

                client = new HttpClient();

                var user = new User()  Username = textBoxUsername.Text.Trim(), Password = StringUtils.Crypt(textBoxPassword.Text.Trim()) ;

                var url = Properties.Settings.Default.ServerBaseUrl + @"/api/account/VerifyUserNamePassword";
                response = await client.PostAsync(url, user.AsJson());

                if (response.IsSuccessStatusCode)    // Check the response StatusCode
                
                    var serSettings = new JsonSerializerSettings()  TypeNameHandling = TypeNameHandling.All ;   
                    string responseBody = await response.Content.ReadAsStringAsync();

                    var loggedUser = JsonConvert.DeserializeObject<User>(responseBody, serSettings);

                    if (loggedUser.IsLogged == false && loggedUser.UserId == Guid.Empty)
                    
                        logger.Warn(Properties.Resources.LOGINUsernameOrPasswordWrong + " Username:" + user.Username);

                        BeginInvoke((Action)(() =>
                        
                            materialLabelErrMessage.Text = Properties.Resources.LOGINUsernameOrPasswordWrong;
                            materialLabelErrMessage.Visible = true;
                            pbLogin.Visible = false;
                            btnOK.Enabled = true;
                        ));
                    
                    else
                    
                        logger.Info(Properties.Resources.LOGINPassed + " Username:" + user.Username);

                        BeginInvoke((Action)(() =>
                        
                            materialLabelErrMessage.Text = string.Empty;
                            materialLabelErrMessage.Visible = false;

                            Program.UserInfo = loggedUser;

                            DialogResult = DialogResult.OK;
                            pbLogin.Visible = false;

                        ));
                    
                
                else if (response.StatusCode == HttpStatusCode.Forbidden)
                
                    pbLogin.Visible = false;
                    btnOK.Enabled = true;

                    materialLabelErrMessage.Text = Properties.Resources.LOGINUsernameOrPasswordWrong;
                    materialLabelErrMessage.Visible = true;
                    logger.Warn(Properties.Resources.LOGINUsernameOrPasswordWrong + " Username:" + user.Username);
                
                else
                
                    pbLogin.Visible = false;
                    btnOK.Enabled = true;

                    materialLabelErrMessage.Text = Properties.Resources.LOGINCannotConnectToServer;
                    materialLabelErrMessage.Visible = true;

                    logger.Error("Reason: " + response.ReasonPhrase + " Message: " + response.RequestMessage + " Username:" + user.Username);
                
            
            catch (ObjectDisposedException ex)
            
                logger.Error("Login has been canceled. " + ex.Message);
                pbLogin.Visible = false;
                btnOK.Enabled = true;
            
            catch (Exception ex)
            
                logger.Error(Properties.Resources.LOGINUsernameOrPasswordWrong + " " + ex.Message);
                pbLogin.Visible = false;
                btnOK.Enabled = true;
            
        

        void CancelLogin()
        
            if (client != null)
             
                client.CancelPendingRequests();
                client = null;
            
        
    

【讨论】:

以上是关于正确中止或取消 PostAsync的主要内容,如果未能解决你的问题,请参考以下文章

NET问答: 如何取消或中止 Task 执行 ?

如何放弃或取消 std::thread

中止 xmlhttprequest

pycharm 取消 rebase 操作

Qt QNetworkAccessManager 中止身份验证

使用单个取消令牌添加中止所有任务