You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

传递ImageSharp Image参数时触发ObjectDisposedException的解决咨询

问题原因

你遇到的ObjectDisposedException是因为GetTicketWithQRCode方法中使用了using var声明imageWithQRCode对象。using关键字会在方法执行完毕(返回结果后)自动调用对象的Dispose方法释放资源,导致后续Send方法尝试操作这个已被释放的Image对象时触发异常。

解决方案

有两种可行的处理方式,根据你的场景选择:

方案一:移除imageWithQRCode的using声明,由调用方管理生命周期

修改GetTicketWithQRCode方法,去掉imageWithQRCode的using修饰:

async public Task<Image> GetTicketWithQRCode(CancellationToken cancellationToken)
{
    var qrCode = QrCode.EncodeText($@"
        {{
        Id:""{this.TickedGuid}"",
        UserData:""{this.TickedUserData.Name} {this.TickedUserData.Surname}""
        }}
        ", QrCode.Ecc.Quartile);

    using var imageBase = await Image.LoadAsync<Rgba32>($"/var/opt/clubapp/images/{this.Ticket.Image.ImageSrc}", cancellationToken);

    // 移除using,手动管理对象生命周期
    var imageWithQRCode = new Image<Rgba32>(imageBase.Width, imageBase.Height);

    imageWithQRCode.CombineWithBaseImageAndQrCode(imageBase, qrCode, new Size() { Width = 390, Height = 495 }, 250);

    await imageWithQRCode.ResizeToHasMaximumFileSize(1.5, cancellationToken);

    var imageRatio = imageWithQRCode.Width / imageWithQRCode.Height;
    imageWithQRCode.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Max, Size = new Size() { Height = 100, Width = 100 * imageRatio } }));

    return imageWithQRCode;
}

然后在Handle方法中使用完Image对象后手动释放:

public async Task<Unit> Handle(CancellationToken cancellationToken)
{
    ...
    
    var ticketImage = await ticket.GetTicketWithQRCode(cancellationToken);
    try
    {
        _emailService.Send(ticketImage);
    }
    finally
    {
        // 使用完毕后手动释放资源
        ticketImage.Dispose();
    }
    
    return new Unit();
}

方案二:返回处理好的MemoryStream而非Image对象

这种方式更安全,因为可以在GetTicketWithQRCode方法内完成Image对象的释放,避免后续生命周期管理问题:

修改GetTicketWithQRCode返回MemoryStream:

async public Task<MemoryStream> GetTicketWithQRCode(CancellationToken cancellationToken)
{
    var qrCode = QrCode.EncodeText($@"
        {{
        Id:""{this.TickedGuid}"",
        UserData:""{this.TickedUserData.Name} {this.TickedUserData.Surname}""
        }}
        ", QrCode.Ecc.Quartile);

    using var imageBase = await Image.LoadAsync<Rgba32>($"/var/opt/clubapp/images/{this.Ticket.Image.ImageSrc}", cancellationToken);

    using var imageWithQRCode = new Image<Rgba32>(imageBase.Width, imageBase.Height);

    imageWithQRCode.CombineWithBaseImageAndQrCode(imageBase, qrCode, new Size() { Width = 390, Height = 495 }, 250);

    await imageWithQRCode.ResizeToHasMaximumFileSize(1.5, cancellationToken);

    var imageRatio = imageWithQRCode.Width / imageWithQRCode.Height;
    imageWithQRCode.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Max, Size = new Size() { Height = 100, Width = 100 * imageRatio } }));

    var memoryStream = new MemoryStream();
    // 将Image保存到流中
    await imageWithQRCode.SaveAsPngAsync(memoryStream, cancellationToken);
    // 重置流的位置到开头,确保后续能正确读取
    memoryStream.Position = 0;
    return memoryStream;
}

修改Send方法接收MemoryStream:

public string Send(MemoryStream imageStream)
{
    var message = new MimeMessage();

    [...]

    var body = new TextPart("Html")
    {
        Text = @"test"
    };

    var attachment = new MimePart("image", "png")
    {
        Content = new MimeContent(imageStream),
        ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
        ContentTransferEncoding = ContentEncoding.Base64,
    };
    
    ...
}

最后在Handle方法中管理流的生命周期:

public async Task<Unit> Handle(CancellationToken cancellationToken)
{
    ...
    
    var ticketImageStream = await ticket.GetTicketWithQRCode(cancellationToken);
    try
    {
        _emailService.Send(ticketImageStream);
    }
    finally
    {
        ticketImageStream.Dispose();
    }
    
    return new Unit();
}
总结

推荐使用方案二,因为它将Image对象的生命周期完全限制在GetTicketWithQRCode方法内,避免了跨方法的资源管理风险,代码更健壮。

内容的提问来源于stack exchange,提问作者Gersalom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:55:21