Как настроить ASP.NET MVC для обработки загруженных данных независимо от запроса? - PullRequest
1 голос
/ 26 апреля 2011

Я только начинаю изучать ASP.NET MVC. Веб-сайт, над которым я работаю, требует, чтобы пользователь загружал файлы XML, которые загружаются в базу данных SQL через NHibernate. Теперь это работает нормально с небольшим XML-файлом, но как только я попробовал больший файл, у меня начались проблемы.

Когда я загружаю файл большего размера, для записи данных в базу данных требуется некоторое время, поэтому на конце пользователя они застряли "в ожидании локального хоста ...", пока запись в базу данных не будет завершена и Upload() Метод действия возвращает представление.

Вместо этого я хотел бы настроить что-то вроде большинства популярных сайтов загрузки фильмов, где, как только пользователь загружает файл, он сразу же отправляется на другую страницу с сообщением, что-то вроде «Ваша загрузка обрабатывается, пожалуйста, приходите назад позже ".

Я немного поработал с многопоточностью, но я почти не чувствую, что знаю, что делаю. Хотя, только сейчас я, кажется, получил свою сидячую работу так, как хочу, используя System.Threading.ThreadPool.

Является ли использование пула потоков, как этот, лучшим способом решения этой проблемы?

Вот мой метод действия Upload ().

public ActionResult Upload(int id)
{
    //check the type of request
    if (Request.RequestType == "GET")
        {
            //get GET show the upload form
            return View();
        }
        else if (Request.RequestType == "POST")
        {
            //if POST process uploaded file data
            if (Request.Files.Count == 1)
            {
                //copy the upload stream into a memory stream
                System.IO.MemoryStream memStream = new System.IO.MemoryStream();
                Request.Files[0].InputStream.CopyTo(memStream);

                //send the the memorystream, id, and username to a new Thread pool work item
                System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WriteUploadToDb), new WriteUploadToDbData(id, memStream,User.Identity.Name));

                //send the user to a page
                ViewBag.Message = "Your file is being processed. Please come back later...";
                return RedirectToAction("Reports", new { ID = id });
            }
            else
            {
                throw new Exception("Multiple report files uploaded!");
            }
        }
    }

А вот мой метод WriteUploadToDb (), который запускается в ThreadPool.

private static void WriteUploadToDb(object obj)
    {
        WriteUploadToDbData updateData = (WriteUploadToDbData)obj;

        //resets the stream position
        updateData.Data.Position = 0;

        //creates a new Nhibernate session
        using (var session = MvcApplication.SessionFactory.OpenSession())
        {
            using (var trans = session.BeginTransaction())
            {
                var proj = session.Get<Project>(updateData.ProjectID);

                //adds the xml data into the Project
                System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
                xmlDoc.Load(updateData.Data);
                proj.AddReport(xmlDoc, updateData.UserName);

                //saves the project to the db
                session.Update(proj);
                trans.Commit();
            }
        }

        //disposes the memory stream
        updateData.Data.Dispose();
    }

1 Ответ

1 голос
/ 26 апреля 2011

Зависит от объема, на котором вы это делаете.

Для тома от низкого до скромного, запуск асинхронного потока для завершения работы вполне подойдет.Однако данный веб-сервер может обрабатывать только столько потоков (пул потоков имеет конечный, хотя и настраиваемый размер).

Для приложений большого объема я предпочитаю, чтобы веб-сервер обрабатывал только веб-запросы и переносил любую асинхронную обработку на другой сервер.Это может быть достигнуто, например, с помощью MSMQ или путем записи в файл журнала, который другой сервер берет и обрабатывает (последний обычно используется в приложениях с очень большим объемом, поскольку запись в файл является очень быстрым и очень надежным процессом).

Причина, по которой я предпочитаю идти по этому пути, заключается в том, что я могу масштабировать для обработки входящих запросов веб-служб / веб-сайтов независимо от обработки асинхронных рабочих элементов, что обеспечивает больший контроль над масштабированием.

...