나는 웹상에서 나는 (로컬로 다운로드 한) 분류 이미지의 매우 큰 데이터베이스를 가지고있다.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);
}
}
Parallel.ForEach는 내부적으로 하나 개 이상의 스레드를 관리하지만 여전히 처리 synchonously 현재 스레드를 차단합니다. 새 스레드를 시작하고 이미지 초기화 논리를 포함하는 메소드를 호출하여 페이지 수명주기를 계속할 수 있습니까? – DvS
답장을 보내 주셔서 감사합니다 다리우스, 내가 더 명확해야합니다 - 그것은 이미 별도의 스레드에서 실행되어야합니다, 나는이 같은 parallel.foreach를 실행하는 방법을 시작 : 스레드 obj = new Thread (new ThreadStart (RunPreLoadContent)); obj.IsBackground = true; obj.Start(); 세션이 끝날 때 뭔가 쓰여지므로 스레드를 시작할 때 뭔가 잘못된 것을하지 않으면 mainthread를 막지 않아야합니다. – SimonDK
Parallel.ForEach가 처리를 끝내면 세션 상태에 어떻게 접근합니까? 또한 처리가 완료되기까지 어느 시점에서 페이지 수명주기가 기다리고 있습니까? 그렇다면 어떻게? 몇 가지 코드를 게시하는 것이 좋습니다 ... – DvS