图像大小调整的异步任务

时间:2015-04-23 07:37:40

标签: c# asp.net asynchronous transactions

这是我的图像缩放器类:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;
using System.Threading.Tasks;
public class ImageResize
{
    private static ImageCodecInfo jpgEncoder;
    public async static void ResizeImage(string inFile, string outFile,
    double maxDimension, long level)
    {
        byte[] buffer;
        using (Stream stream = new FileStream(inFile, FileMode.Open))
        {
            buffer = new byte[stream.Length];
            await Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead,
            buffer, 0, buffer.Length, null);
        }
        using (MemoryStream memStream = new MemoryStream(buffer))
        {
            using (Image inImage = Image.FromStream(memStream))
            {

                double width;
                double height;
                if (inImage.Height < inImage.Width)
                {
                    width = maxDimension;
                    height = (maxDimension / (double)inImage.Width) * inImage.Height;
                }
                else
                {
                    height = maxDimension;
                    width = (maxDimension / (double)inImage.Height) * inImage.Width;
                }
                using (Bitmap bitmap = new Bitmap((int)width, (int)height))
                {
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {

                        graphics.SmoothingMode = SmoothingMode.HighQuality;
                        graphics.InterpolationMode =
                        InterpolationMode.HighQualityBicubic;
                        graphics.DrawImage(inImage, 0, 0, bitmap.Width, bitmap.Height);

                        if (inImage.RawFormat.Guid == ImageFormat.Jpeg.Guid)
                        {
                            if (jpgEncoder == null)
                            {
                                ImageCodecInfo[] ici =
                                ImageCodecInfo.GetImageDecoders();
                                foreach (ImageCodecInfo info in ici)
                                {
                                    if (info.FormatID == ImageFormat.Jpeg.Guid)
                                    {
                                        jpgEncoder = info;
                                        break;
                                    }
                                }
                            }
                            if (jpgEncoder != null)
                            {
                                EncoderParameters ep = new EncoderParameters(1);
                                ep.Param[0] = new EncoderParameter(Encoder.Quality,
                                level);
                                bitmap.Save(outFile, jpgEncoder, ep);
                            }
                            else
                                bitmap.Save(outFile, inImage.RawFormat);
                        }
                        else
                        {
                            //
                            // Fill with white for transparent GIFs
                            //
                            graphics.FillRectangle(Brushes.White, 0, 0, bitmap.Width,
                            bitmap.Height);
                            bitmap.Save(outFile, inImage.RawFormat);
                        }
                    }
                }
            }
        }
    }
}

这是我的注册按钮服务器点击:

    HttpPostedFile file = Request.Files["ctl00$cph$postFile"];
    string FileName = "";

    if (file.ContentLength > 0)
    {
        string[] ValidExt = { ".jpg", ".jpeg" };

        string fileExt = Path.GetExtension(file.FileName).ToLower();

        if (Array.IndexOf(ValidExt, fileExt) < 0)
        {
            return;
        }
        if (file.ContentLength / 1024 > 5120)
        {
            return;
        }
        string path = Server.MapPath("~/upload/image_upload/ads/");
        string[] s = file.FileName.Split('\\');

        FileName = System.IO.Path.GetFileName(s[s.Length - 1]);
        while (System.IO.File.Exists(path + FileName))
        {
            Random r = new Random();
            int rn = (DateTime.Now + r.Next().ToString()).GetHashCode();
            FileName = rn + " " + FileName;
        }
        string FullPath = path + FileName;
        file.SaveAs(FullPath);
        ImageResize.ResizeImage(FullPath, FullPath, 800, 80);
        string thPath = path + "th\\" + FileName;
        file.SaveAs(thPath);
        ImageResize.ResizeImage(thPath, thPath, 300, 90);

    }
    SqlConnection con = new SqlConnection(cs);

    StringBuilder sb = new StringBuilder();
    sb.Append("BEGIN TRY BEGIN TRANSACTION");
    sb.Append(" declare @result bit=0; declare @ad_id int;");
    sb.Append("INSERT INTO tbl_ads(ad_title,ad_brief,ad_text,ad_pic,ad_datesave,ad_is_accept,ad_is_show,ad_visit,ad_type,ad_user,ad_is_slide)");
    sb.Append(" VALUES(@ad_title,@ad_brief,@ad_text,@ad_pic,@ad_datesave,@ad_is_accept,@ad_is_show,@ad_visit,@ad_type,@ad_user,@ad_is_slide);");
    sb.Append("set @ad_id=SCOPE_IDENTITY();");

    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;

    cmd.Parameters.AddWithValue("@ad_title", txt_title.Value);
    cmd.Parameters.AddWithValue("@ad_brief", txt_brief.Value);
    cmd.Parameters.AddWithValue("@ad_text", txt_full.Value);
    cmd.Parameters.AddWithValue("@ad_pic", FileName);
    cmd.Parameters.AddWithValue("@ad_datesave", PersianDate.GetDate(0));
    cmd.Parameters.AddWithValue("@ad_is_accept", chk_accept.Checked);
    cmd.Parameters.AddWithValue("@ad_is_show", chk_show.Checked);
    cmd.Parameters.AddWithValue("@ad_visit", 0);
    cmd.Parameters.AddWithValue("@ad_type", lst_type.Value);
    cmd.Parameters.AddWithValue("@ad_user", -1*(int)Session["u_id"]);
    cmd.Parameters.AddWithValue("@ad_is_slide", chk_slide.Checked);


    string[] SubcatIds = inp_subcats.Value.Split(',');
    string[] StateIds = inp_states.Value.Split(',');
    string[] CityIds = inp_cities.Value.Split(',');


    if (CatIds[0] != "")
    {
        for (int i = 0; i < CatIds.Length; i++)
        {
            cmd.Parameters.AddWithValue("@cat_id" + i, CatIds[i]);
            sb.Append("INSERT INTO tbl_inf_adcat(ad_id,cat_id) VALUES(@ad_id,@cat_id" + i + ");");
        }
    }

    if (SubcatIds[0] != "")
    {
        for (int i = 0; i < SubcatIds.Length; i++)
        {
            cmd.Parameters.AddWithValue("@subcat_id" + i, SubcatIds[i]);
            sb.Append("INSERT INTO tbl_inf_adsubcat(ad_id,subcat_id) VALUES(@ad_id,@subcat_id" + i + ");");
        }
    }

    if (StateIds[0] != "")
    {
        for (int i = 0; i < StateIds.Length; i++)
        {
            cmd.Parameters.AddWithValue("@state_id" + i, StateIds[i]);
            sb.Append("INSERT INTO tbl_inf_adstate(ad_id,state_id) VALUES(@ad_id,@state_id" + i + ");");
        }
    }

    if (CityIds[0] != "")
    {
        for (int i = 0; i < CityIds.Length; i++)
        {
            cmd.Parameters.AddWithValue("@city_id" + i, CityIds[i]);
            sb.Append("INSERT INTO tbl_inf_adcity(ad_id,city_id) VALUES(@ad_id,@city_id" + i + ");");
        }
    }


    sb.Append("COMMIT set @result=1 select @result  END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK select  @result END CATCH");

    cmd.CommandText = sb.ToString();

    try
    {

        con.Open();

        bool result = Convert.ToBoolean(cmd.ExecuteScalar());

        if (result == true)
        {
            ClientAlert.modalBoxInfo(this, "success");

        }
        else
        {
            ClientAlert.modalBoxAlert(this, "error");
        }

    }
    catch
    {
        ClientAlert.modalBoxAlert(this, "error");
    }
    finally
    {
        con.Close();
    }

}

但是当我想运行此方法时会发生错误:

在异步操作仍处于挂起状态时完成异步模块或处理程序。

我在页面指令中使用了 Async =“true”,我在visual studio中测试它,但在真正的主机中它有错误。 是因为我使用了交易吗? 提前问候。

1 个答案:

答案 0 :(得分:1)

不,这是因为

await Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead,
        buffer, 0, buffer.Length, null);

棘手的部分是您的async方法正在返回void。这是一个很大的禁忌,除非你知道你在做什么(你现在显然不知道)。让它返回Task,并且对于所有其他调用者一直返回到请求处理程序本身。这将允许您将等待的回调封送回原始请求线程 - 否则,请求将简单地结束,从而导致回调对已完成的请求起作用。

要让await代码正常工作,您需要拥有这个完整的Task链 - 返回方法,就这么简单。否则,在某些时候你只是调用一个void - 返回方法,它立即返回,然后继续下一个语句,而后台任务仍在运行。

,如果您希望这是一个即发即弃的操作,而不让请求等待调整大小完成,您可以强制await不要尝试编组回请求线程:

await Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead,
        buffer, 0, buffer.Length, null).ConfigureAwait(false);

此外,首先将输入文件保存到文件中是个坏主意。您拥有直接使用输入流所需的一切,为什么要保存中间文件?在一些文件锁定问题上很容易失败。

,在使用此类即发即弃任务时,请确保执行正确的错误处理。根据.NET框架版本和配置,未等待的Task中的未处理异常将终止整个过程。