2014-09-15 3 views
0

나는 웹상에서 나는 (로컬로 다운로드 한) 분류 이미지의 매우 큰 데이터베이스를 가지고있다.ASP.Net 및 Parallel.Foreach는 버튼이 작동을 멈추게합니까?

웹 사이트가있어서 (로컬로)이 작업을 수행 할 수 있지만 db 쿼리는 오래 걸리므로 다음 페이지를 "미리로드"하는 아이디어가 있으므로 페이지의 첫 번째로드 만 느려질 수 있습니다 . 나는 세션에서 별도의 스레드에로드 된 항목의 목록을 저장합니다. 여태까지는 그런대로 잘됐다. 나는 더 이상 최적화하고 싶었고 가장 오래 걸린 것에 대한 테스트를했고 이미지를로드하여 이미지를로드하여 크기를 조정해야하는지 확인했습니다 (이미지 높이와 너비를 img obj로 설정). parallel.foreach 루프가있는이 -하지만 이렇게하면 페이지의 제 단추가 응답하지 않습니까? 나는 버튼을 누르면 페이지가 Page_Load 이벤트를 통해 실행 볼 수 있지만 버튼 "코드"에 도달하지 않습니다 보호 가상 무효 btnSaveFollowPosts_Click (개체를 보낸 사람을 EventArgs입니다 E) {...}

내가 뭘 잘못하고 있니? 나는 그것이 paralellelism의 정도를 1로 제한하려고 시도했다.

업데이트 - 코드 : 을 졸이다하려고 :

protected void Page_Load(object sender, EventArgs e) 
{ 
    Search(false); 
} 

protected void Search(bool updateCounters) 
{ 
    if (Session[SessionItems] == null) 
    { 
     if (Session[SessionItemsCache] == null) 
     { 
      //if is being constructed, wait, else construct 
      //if construction is not running 
      if (Session[SessionCacheConstructionRunning] == null) 
      { 
       StartPreLoadContent(); 
      } 

      while (Session[SessionCacheConstructionRunning] != null) 
      { 
       Thread.Sleep(25); //block main thread untill items ready 
      } 
     } 

     List<ContentView> contentViewList = Session[SessionItemsCache] as List<ContentView>; 
     Session[SessionItemsCache] = null; //clean preload cache 
     Session[SessionItems] = contentViewList; //save in current usage storage 

     Filltable(ref tblContent, contentViewList); 

     //preload next batch 
     StartPreLoadContent(); 
    } 
    else 
    { 
     List<ContentView> contentViewList = Session[SessionItems] as List<ContentView>; //get items from session 
     Session[SessionItems] = contentViewList; //save in current usage storage 

     Filltable(ref tblContent, contentViewList); 
    } 
} 

protected void StartPreLoadContent() 
{ 
    Session[SessionCacheConstructionRunning] = true; 

    //start task 
    Thread obj = new Thread(new ThreadStart(RunPreLoadContent)); 
    obj.IsBackground = true; 
    obj.Start(); 
} 

protected void RunPreLoadContent() 
{ 
    using (DBEntities entities = new DBEntities()) 
    { 
     entities.CommandTimeout = 86400; 

     IQueryable<ContentView> query = entities.ContentView.Where(some criterias);        

     List<ContentView> contentViewListCache = query.ToList(); 

     ParallelOptions options = new ParallelOptions(); 
      options.MaxDegreeOfParallelism = 7; 

      Parallel.ForEach(contentViewListCache, options, content => 
      {     
       try 
       { 
        Interlocked.Increment(ref imageSizeCount); 

        string path = Path.Combine(basePath, content.LocalPath); 
            int imageSize = 150; 

        using (System.Drawing.Image realImage = System.Drawing.Image.FromFile(path)) 
        { 
          double scale = 0; 

         if (realImage.Height > realImage.Width) 
         { 
          scale = (double)realImage.Height/imageSize; 
         } 
         else 
         { 
          scale = (double)realImage.Width/imageSize; 
         } 

         if (scale > 1) 
         { 
          content.ImageHeight = (int)((double)realImage.Height/scale); 
          content.ImageWidth = (int)((double)realImage.Width/scale); 

          content.ImageScaled = true; 
         } 
         content.ShowImage = true; 
        } 
       } 
       catch (Exception) 
       { 
       } 
      }); 

     Session[SessionItemsCache] = contentViewListCache; 
     Session[SessionCacheConstructionRunning] = null; //cache ready 
    } 

    protected virtual void btnSave_Click(object sender, EventArgs e) 
     { 
      try 
      { 
       //save 
       ...some reading and saving going on here... 

       //update 
       Session[SessionItems] = null; 
       Search(true); 
      } 
      catch (Exception error) 
      { 
       ShowError(error); 
      } 
     } 
+0

Parallel.ForEach는 내부적으로 하나 개 이상의 스레드를 관리하지만 여전히 처리 synchonously 현재 스레드를 차단합니다. 새 스레드를 시작하고 이미지 초기화 논리를 포함하는 메소드를 호출하여 페이지 수명주기를 계속할 수 있습니까? – DvS

+0

답장을 보내 주셔서 감사합니다 다리우스, 내가 더 명확해야합니다 - 그것은 이미 별도의 스레드에서 실행되어야합니다, 나는이 같은 parallel.foreach를 실행하는 방법을 시작 : 스레드 obj = new Thread (new ThreadStart (RunPreLoadContent)); obj.IsBackground = true; obj.Start(); 세션이 끝날 때 뭔가 쓰여지므로 스레드를 시작할 때 뭔가 잘못된 것을하지 않으면 mainthread를 막지 않아야합니다. – SimonDK

+0

Parallel.ForEach가 처리를 끝내면 세션 상태에 어떻게 접근합니까? 또한 처리가 완료되기까지 어느 시점에서 페이지 수명주기가 기다리고 있습니까? 그렇다면 어떻게? 몇 가지 코드를 게시하는 것이 좋습니다 ... – DvS

답변

1

내가 이전에 의견에 동의 : 당신은 아마 페이지 수명주기 초기에이 논리를해야한다. OnInit를 무시하고 거기에 넣는 것을 고려하십시오.

또한, (윈도우하지 웹 프로그래밍에 더 적합하다) 현재 스레드 코드 대신 코드 행을 시도 할 수 :

using System.Threading.Tasks; 

Task.Run(() => { RunPreLoadContent(); }); 
+0

Preinit 및 Task.Run으로 변경되었으며 이제 작동합니다 - 감사합니다! – SimonDK

+0

굉장! 다행히 문제가 해결되었습니다. – DvS