当前位置: 首页 > 知识库问答 >
问题:

取消postAsync时出现ObjectDisposedException

权浩邈
2023-03-14

我的 Xamarin 应用程序中有以下两个类,用于将图像上传到服务器:

public class ProfileApi : IDisposable
{
    public Uri BaseUri { get; private set; }
    private HttpClientHandler _messageHandler;

    public ProfileApi (string baseUri, HttpClientHandler messageHandler)
    {
        BaseUri = new Uri (baseUri, UriKind.Absolute);
        _messageHandler = messageHandler;
    }

    protected HttpClient CreateHttpClient ()
    {
        var httpClient = new HttpClient (_messageHandler, true) {
            BaseAddress = BaseUri
        };
        return httpClient;
    }


    public async Task SetProfilePicture (Stream picture, CancellationToken cancellationToken)
    {
        using(var client = CreateHttpClient ())
        {
            using(var copy = new MemoryStream())
            {
                picture.Position = 0;
                picture.CopyTo(copy);
                copy.Position = 0;

                var content = new StreamContent (copy);
                content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue ("image/png");

                var response = await client.PostAsync ("post", content, cancellationToken);    

                Debug.WriteLine ("Finished!"); 
            }
        }
    }

    public void Dispose ()
    {
        _messageHandler.Dispose ();
        _messageHandler = null;
    }
}

public class ProfileDownloader
{
    static readonly Lazy<ProfileDownloader> lazy = new Lazy<ProfileDownloader> (() => 
        new ProfileDownloader ()
    );

    public static ProfileDownloader Instance {
        get {
            return lazy.Value;
        }
    }

    ProfileDownloader (){}

    CancellationTokenSource _uploadCancellationSource;

    public async Task UploadImage (Stream image)
    {
        if (AreProfileAndImageBeingUploaded ()) {
            CancelProfileAndImageUpload ();
            return;
        }

        _uploadCancellationSource = new CancellationTokenSource ();

        using (var ProfileApi = new ProfileApi ("http://httpbin.org", new NativeMessageHandler ())) 
        {
            var imageTask = ProfileApi.SetProfilePicture (image, _uploadCancellationSource.Token);

            try {

                await imageTask;
                _uploadCancellationSource = null;

            } catch (OperationCanceledException ex) {
                Debug.WriteLine (string.Format ("Cancelled! : {0}", ex.Message)); 

            } catch (Exception ex) {
                Debug.WriteLine (string.Format ("Exception! : {0}, {1}", ex.Message, ex.Source));
            }
        }
    }

    public bool AreProfileAndImageBeingUploaded ()
    {
        return _uploadCancellationSource != null;
    }

    public void CancelProfileAndImageUpload ()
    {
        if (_uploadCancellationSource != null) {
            _uploadCancellationSource.Cancel ();
            _uploadCancellationSource = null;
        }
    }
}

每当我在应用程序的UI中按下按钮时,都会调用UploadImage方法。

var image = UIImage.FromFile ("Images/SpongeBob.png");
using (var stream = image.ToStream ()) {        
    ProfileDownloader.Instance.UploadImage (stream);
}

这就是我所做的:

  1. 按两次按钮,将调用UploadImage两次。第一次开始上传,第二次取消上传,我会收到TaskCancelledException
  2. 我又按了两次按钮。第一次启动上载,但第二次导致ObjectDisposedException

有谁知道为什么 2 中描述的异常。被扔了?

使现代化

下面是异常的堆栈跟踪。它被抛出到带有<code>await imageTask</code>的行上。

System.ObjectDisposedException: The object was used after being disposed.   at System.Net.WebConnection.EndWrite (System.Net.HttpWebRequest request, Boolean throwOnError, IAsyncResult result) [0x0002c] in 
//Library/Frameworks/Xamarin.iOS.framework/Versions/8.10.1.64/src/mono/mcs/class/System/System.Net/WebConnection.cs:1071 at System.Net.WebConnectionStream.WriteAsyncCB (IAsyncResult r) [0x00013] in 
//Library/Frameworks/Xamarin.iOS.framework/Versions/8.10.1.64/src/mono/mcs/class/System/System.Net/WebConnectionStream.cs:458  --- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/mcs/class/corlib/System.Runtime.ExceptionServices/ExceptionDispatchInfo.cs:61    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:201 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:170 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:142 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:477 at System.Net.Http.HttpClientHandler+c__async0.MoveNext () 0x002f4] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs:344  --- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/mcs/class/corlib/System.Runtime.ExceptionServices/ExceptionDispatchInfo.cs:61 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:201 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:170 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:142 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter[System.Net.Http.HttpResponseMessage].GetResult () [0x00000] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:580 at System.Net.Http.HttpClient+c__async0.MoveNext () [0x000a9] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:274  --- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/mcs/class/corlib/System.Runtime.ExceptionServices/ExceptionDispatchInfo.cs:61 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:201 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:170 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:142 at System.Runtime.CompilerServices.TaskAwaiter`1[System.Net.Http.HttpResponseMessage].GetResult () [0x00000] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:372 at Shared.ProfileApi+c__async0.MoveNext () [0x00114] in 
/Users/mku/Documents/Private projects/Xamarin/Example/Shared/ProfileApi.cs:46  --- End of stack trace from previous location where exception was thrown ---   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/mcs/class/corlib/System.Runtime.ExceptionServices/ExceptionDispatchInfo.cs:61 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:201 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:170 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:142 at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in 
/Users/builder/data/lanes/1503/e6ebd18b/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:124 at Shared.ProfileDownloader+c__async0.MoveNext () [0x000b1] in 
/Users/mku/Documents/Private projects/Xamarin/Example/Shared/ProfileDownloader.cs:42

共有2个答案

孙玮
2023-03-14

您需要等待<code>UploadImage</code>,否则流将在调用后立即释放。

试试这个:

var image = UIImage.FromFile ("Images/SpongeBob.png");
using (var stream = image.ToStream ()) {        
    awaProfileDownloader.Instance.UploadImage (stream);
}

您必须将包含该代码的方法更改为异步方法。

卞俊贤
2023-03-14

事实证明,这实际上是Mono中的一个错误,现已修复,并将在4.2版中发布。

链接到Xamarin的Bugzilla中的错误报告

 类似资料:
  • (不要害怕这个大的描述,我只是想具体一些,这样回答者就更容易了) 我正在使用ASP. Net Core 2.1构建一个具有外部登录功能的Web应用程序。但是当外部(facebook)登录被取消并且facebook重定向到源应用程序时,发生了内部服务器错误。这意味着,您单击了Facebook外部登录按钮,然后通过单击“现在不行”按钮取消了它。Facebook重定向回您的应用程序();然后瞧——异常。

  • 我正在尝试使用以下代码在Spyder中读取带有tabla py的PDF文件: 但是,当我运行此命令时,会出现以下错误: CalledProcessError:命令“['java','-Dfile.encoding=UTF8','-jar','tabla-jar路径','-pages','1','-guess',PDF文件路径']'返回非零退出状态1。 通过升级到Java8,类似的问题也得到了解决,

  • 我使用jax-ws 2.2.7来生成web服务。操作签名是: TKS!!!

  • 问题内容: 我试图定义一个函数来使矩形的周长。这是代码: 我想我没有留下任何争论或类似的话题。 问题答案: 像这样运行它会产生: 我怀疑IDLE只是将单个字符串传递给您的脚本。首先是对整个字符串进行细化。请注意,如果在调用以下命令后放入一些打印语句,会发生什么情况: 运行产品 请注意,第一个print语句将打印整个字符串。第二个调用引发(文件结束错误)。 因此,一个简单的管道(例如我使用的管道)仅

  • 问题内容: 我使用以下代码发送邮件。文本消息发送正常,但带有附件的邮件不起作用,它给出了异常。 javax.mail.MessagingException:发送消息时发生IOException;嵌套的异常是:javax.activation.UnsupportedDataTypeException:MIME类型为multipart / mixed的无对象DCH;boundary =“ ---- =

  • 我在使用discord机器人添加此发送消息时遇到了一个奇怪的错误。我在学习Scratch教程 结果:- `(节点:8480)未经处理的PromisejectionWarning:DiscordAPIError:在C:\Users\Deepanshu\node\u modules\discord处缺少访问权限。js\src\client\rest\RequestHandlers\Sequential