在完成之前停止for-loop中间

时间:2015-11-25 15:14:25

标签: c# asp.net solr

我们正在asp.net c#project中使用Solrnet将文档索引到Solr中。我们要求Solr DIH不能使用,因此我们使用以下代码将产品分批索引到Solr:

decimal cycleCount = ProductCount / batchSize;
for (int i = 0; i <= Math.Round(cycleCount); i++)
{       
   var Products = Products(batchSize, languageId, storeId).ToList();
   solrCustomWorker.Add(solrProducts);
   solrCustomWorker.Commit();
}

凭借庞大的文档大小,完成整个过程需要花费大量时间(大部分时间需要几个小时),有时我们需要通过手动干预来中断此过程。

但是,我不确定如何在完成之前停止这两个索引批处理循环。具有大批量文档的单个循环,需要几秒钟才能完成,然后提交。但考虑到巨大的没有。在执行完整索引时,文档需要几个小时,我们无法在两者之间停止此过程。

任何想法 - 如何在中间停止这个过程..我无法弄清楚应该在这里做什么?

请建议。

2 个答案:

答案 0 :(得分:5)

您可以采取以下两种方法:

1使用全局变量(这不是一个好的解决方案,希望有明显的原因):

public static bool KeepRunning;

...

for (int i = 0; i <= Math.Round(cycleCount); i++)
{
    if (KeepRunning)
    {    
        var Products = Products(batchSize, languageId, storeId).ToList();
        solrCustomWorker.Add(solrProducts);
        solrCustomWorker.Commit();
    }
}

2使用回调检查是否继续运行:

public void SomeMethod(Func<bool> keepRunning)
{
    for (int i = 0; i <= Math.Round(cycleCount); i++)
    {
        if (keepRunning())
        {    
            var Products = Products(batchSize, languageId, storeId).ToList();
            solrCustomWorker.Add(solrProducts);
            solrCustomWorker.Commit();
        }
    }
}

第二种方法的优点是您可以将决策逻辑与索引逻辑分离并避免全局变量,例如通过捕获是否在对长时间运行的进程和事件处理程序的异步调用的闭包内继续运行

答案 1 :(得分:0)

另一种方法,也许有点迂回,是创建一个应用程序文件&#34; Global.asax&#34;并尝试使用here所述的后台工作程序。您还可以查看我的winforms here

示例
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;

namespace AspNetBackgroundProcess
{
    public static BackgroundWorker worker = new BackgroundWorker()
    public static bool stopWorker = false;

    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            worker.DoWork += new DoWorkEventHandler(DoWork);
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
            // Calling the DoWork Method Asynchronously
            worker.RunWorkerAsync();
        }

        protected void Application_End(object sender, EventArgs e)
        {
            if (worker != null)
                worker.CancelAsync();
        }

         //Start Process
        private void button1_Click(object sender, EventArgs e)
        {
            worker.RunWorkerAsync();
        }

        //Cancel Process
        private void button2_Click(object sender, EventArgs e)
        {
             //Check if background worker is doing anything and send a cancellation if it is
            if (worker.IsBusy)
            {
                worker.CancelAsync();
            }

        }

        private static void DoWork(object sender, DoWorkEventArgs e)
        {
            decimal cycleCount = ProductCount / batchSize; //Depending on where you get these variables, you might consider moving this to the class level along with the other variable declarations
            for (int i = 0; i <= Math.Round(cycleCount); i++)
            {
                //Check if there is a request to cancel the process
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    worker.ReportProgress(0);
                    return;
                }


                var Products = Products(batchSize, languageId, storeId).ToList();
                solrCustomWorker.Add(solrProducts);
                solrCustomWorker.Commit();
            }
        }
        private static void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            if (worker != null)
            {
                System.Threading.Thread.Sleep(3000);
                if (!stopWorker)
                {
                    worker.RunWorkerAsync();
                }
                else
                {
                    while (stopWorker)
                    {
                        Thread.Sleep(6000);
                    }
                    worker.RunWorkerAsync();
                }
            }
        }
    }
}