【问题标题】:Notify the View after async Task is completed in MVC在 MVC 中完成异步任务后通知视图
【发布时间】:2020-04-14 02:36:03
【问题描述】:

我有一个视图,我通过 ajax 将数据发送到 MVC 中的一个操作。我只想在任务完成时在视图中收到通知。我遇到的问题是我之前是否收到通知,或者如果我等到任务完成我的视图被阻止。这是我所做的一个例子:

function UploadFile(file) {
    $.ajax({
        url: '/Home/Upload',
        type: 'POST',
        data: file,
        success: function (result) {
            alert(result);

        }
    });
}


[HttpPost]
public async Task<ActionResult> Upload(httpPostedFileBase file)
{
        NewFile service = new NewFile((long)Session["UserId"]);

        Thread thread = new Thread(() =>service.UploadFile(file));
        thread.Start();
        return Json("File Uploaded", JsonRequestBehavior.AllowGet);
}


    public async Task<string> UploadFile(HttpPostedFileBase file) // returns the file Id in Google Drive
    {
        Google.Apis.Drive.v3.Data.File uploadedFile = new Google.Apis.Drive.v3.Data.File();
        try
        {
            if (file != null && file.ContentLength > 0)
            {
                // Check for credentials
                Google.Apis.Drive.v3.DriveService service = Service;
                // Uploads the file to the server in "~/GoogleDriveFiles" folder.
                /*string path = Path.Combine(HttpContext.Current.Server.MapPath("~/GoogleDriveFiles"),*/ // TODO Doesn't work with Unit testing. Must be written manual for testing
                //Path.GetFileName(file.FileName));
                //file.SaveAs(path);
                // Save the metadata of the file
                var FileMetaData = new Google.Apis.Drive.v3.Data.File()
                {
                    Name = Path.GetFileName(file.FileName),
                    MimeType = MimeMapping.GetMimeMapping(file.FileName),
                    Parents = new List<string>
                    {
                       GetReposFolderId()
                    }
                };
                // Create a request for upload
                Google.Apis.Drive.v3.FilesResource.CreateMediaUpload request;
                file.InputStream.Close();
                // Create a stream using the file filepath and filling the request. Then upload.
                using (var stream = new System.IO.FileStream(file.FileName, System.IO.FileMode.Open))
                {
                    request = service.Files.Create(FileMetaData, stream, FileMetaData.MimeType);
                    request.Fields = "id";
                    await request.UploadAsync();//TODO Tuka bavi i ne mozesh da browswash prez papkite dokato ne go kachi na servara
                }
                uploadedFile = request.ResponseBody;
            }
        }
        catch (Exception ex)
        {
            ErrorEngine.RuntimeExceptions runtimeExceptions = new ErrorEngine.RuntimeExceptions();
            runtimeExceptions.ManageException(ex, this);
            return ex.ToString();
        }
        return uploadedFile.Id;
    }

我对 MVC 和一般编码方面的经验并不如您想象的那样。你能帮我解决这个问题吗?

【问题讨论】:

  • 您应该永远调用new Thread(...),除非您正在编写自定义线程调度程序。您应该改用Task.Run(...)

标签: c# asp.net ajax asp.net-mvc asynchronous


【解决方案1】:

简短的回答是你不能......

如果你不想等待处理......那么它永远不会知道......

除非

要么,您使用 poller 并每隔 x 次询问一次,或者使用双向通信....这需要大量编码,但您可以查看 SingalR,然后你可以发出一个消息,所有的监听都可以收到。

所以最简单的......对你来说......是将文件作为一个请求上传并等待响应。

上传和要做什么可以分开,这就是许多网站所做的..您可以使用js,有一个进度条来说明将文件上传到服务器的进度..但是处理o 服务器除非你等待,否则除了我上面所说的或那里的变化之外别无他法。

选项有 pollersocket base tech,或只需等待上传到并完成处理。

上传和处理可以是具有不同响应的单独调用,这是大多数网站所做的......

【讨论】:

  • 感谢您的回答!但是,如果我将文件作为一个请求上传并等待响应,视图将被阻止对吗?
  • 就像我说的那样没有复杂化...。上传一个动作,然后提交一个动作,提交与已上传的文件交互......所以提交只是关于第二个动作。所以用户交互,所以他们想给一个图像......首先他们上传,所以一旦他们选择一个文件就开始上传,然后当它完成时......你可以给他们一个进度条,然后上传后,您可以向他们展示...然后他们可以单击保存/提交,然后使用已上传的文件。显然,您需要先将文件保存在临时位置,然后再保存..get 并执行
  • 谢谢。这就是我需要的!
【解决方案2】:

试试这个:

[HttpPost]
public async Task<JsonResult> Upload(httpPostedFileBase file)
{
    try {
        NewFile service = new NewFile((long)Session["UserId"]);
        await Task.Run(() => service.UploadFile(file));
    } catch (Exception e) {
        Console.WriteLine(e);
    }

    return Json("File Uploaded", JsonRequestBehavior.AllowGet);
}

【讨论】:

  • 您的代码无法编译。您在等待之外没有返回语句。此外,使用 Task.Run 调用 new Thread(...).Start() 有点没用。
  • 是的,我明白您对 Task.Run 的意思,但这不会改变,当线程或任务完成时,我的视图中没有收到任何通知。在任务完成之前,我在 ajax 请求中触发了我的成功函数。我需要的是在任务完成后得到通知,而不会在过程中阻塞视图。
  • Julian - 我已经编辑了我的答案,但没有看到你的完整设置,我做了几个假设,主要是你的文件上传任务是同步的并且作为一个单独的服务工作。如果是这种情况,那么将其包装在 Task.Run 中应该可以工作并在完成时通知您。
  • Keith - 当我把它放在等待任务中时。运行()Veiw 被阻止,直到文件被上传。如果文件很大,可能需要很长时间。如果我没有等待视图不会被阻止,则文件在后台上传,但上传文件时我没有收到通知,因为在上传完成之前触发了 ajax 请求中的成功功能。我想在上传完成时收到通知而不阻塞视图。
  • Julian - 可以发布您的 UploadFile 服务的签名吗?我想知道是不是:public void UploadFile(File SomeFile) 或 public Task UploadFile(File SomeFile)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 1970-01-01
  • 2023-01-17
相关资源
最近更新 更多