ASP.Net和Parallel.Foreach导致按钮停止工作?

时间:2014-09-15 08:46:36

标签: asp.net multithreading parallel.foreach

我有一个非常大的网络图像数据库,我正在分类(在本地下载)。

所以我有一个网站(本地)来做这个,但数据库查询花了很长时间,所以我有一个想法" preload"下一页,这样只有页面的第一次加载才会很慢。我保存会话中单独线程中加载的项目列表。到现在为止还挺好。 我想进一步优化,并对最长时间进行一些测试,并加载图像以检查尺寸,看看是否需要缩放它们(在img obj上设置图像高度和宽度) - 所以我想这样做使用parallel.foreach循环 - 但在执行此操作后,我的页面上的按钮停止响应?当我按下按钮时,我可以看到页面在page_load事件中运行,但它没有到达按钮" code":  protected virtual void btnSaveFollowPosts_Click(object sender,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);
            }
        }

1 个答案:

答案 0 :(得分:1)

我同意之前的评论:您可能应该在页面生命周期的早期执行此逻辑。考虑重写OnInit并将其放在那里。

此外,您可以尝试这行代码而不是当前的线程代码(更适合Windows而不是Web编程):

using System.Threading.Tasks;

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