2011-04-26 21 views
1

我剛開始學習ASP.NET MVC。我正在處理的網站要求用戶上傳通過NHibernate加載到SQL數據庫中的XML文件。這對於一個小XML文件現在可以正常工作,但是一旦我嘗試了一個更大的文件,我開始出現問題。如何設置ASP.NET MVC來處理獨立於請求的上傳數據?

當我上傳一個較大的文件時,需要一段時間才能將數據寫入數據庫,因此在用戶的末端它們會卡住「等待本地主機......」,直到數據庫寫入完成並且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!"); 
      } 
     } 
    } 

這裏是我在ThreadPool上運行的WriteUploadToDb()方法。

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

取決於你在做這件事的音量。

對於低到中等的音量,啓動異步線程來完成工作很好。但是,給定的Web服務器只能處理如此多的線程(線程池具有有限但可配置的大小)。

對於大容量應用程序,我更喜歡讓Web服務器只處理Web請求並將任何異步處理卸載到另一臺服務器。這可以通過例如使用MSMQ或通過寫入另一臺服務器選取和處理的日誌文件(後者通常用於大批量應用程序,因爲寫入文件是一種非常快速且非常可靠的過程)。

我更喜歡走這條路線的原因是,我可以通過擴展來處理傳入的Web服務/網站請求,與異步工作項目的處理無關,允許對擴展進行更多控制。

+0

在可預見的將來,我不認爲這將成爲高容量的網站。大多數情況下,這僅僅是我學習ASP.NET MVC的一個項目。我猜想另一種選擇也可能是將用戶上傳的文件轉儲到另一個程序正在監控的文件夾中? – 2011-04-26 01:25:25

+0

我同意MSMQ,也考慮Windows Azure隊列。 – BZink 2011-04-26 03:00:22

+0

@Eric答:是的,您可以將每個文件單獨轉儲到一個文件夾中。另一個進程(例如Windows服務)可以提取這些文件。 Windows Service主要可以在另一臺服務器上存在,並通過網絡共享訪問該文件。如果有人在捲上執行該操作,則可能需要Web服務器中有2個NIC ......一個用於處理網絡流量,另一個用於文件複製/遠程文件訪問操作。 – 2011-04-26 03:51:53