C# Event.BeginInvoke+;Quartz.NET+;FileSystemWatcher+;Task.runin循环=异常?

C# Event.BeginInvoke+;Quartz.NET+;FileSystemWatcher+;Task.runin循环=异常?,c#,events,asynchronous,multitasking,C#,Events,Asynchronous,Multitasking,我看了这么多,找不到与我的独特问题相匹配的东西 问题是: 我一直在使用Quartz.NET和FileSystemWatcher处理一些代码,基本设置如下 Quartz.NET以15秒的间隔启动计时器。此触发器导致在特定目录中创建文件,文件名格式为*.csv(或*.xml,仅举一个例子)。FileSystemWatcher会注意到该文件并执行一些代码,而这些代码反过来会在同一目录中弹出一个*.csv。现在我知道这将重新触发观察者,它将陷入一个无限循环中——这是我第一次打算这么做 当此代码运行时,我

我看了这么多,找不到与我的独特问题相匹配的东西

问题是: 我一直在使用Quartz.NET和FileSystemWatcher处理一些代码,基本设置如下

Quartz.NET以15秒的间隔启动计时器。此触发器导致在特定目录中创建文件,文件名格式为*.csv(或*.xml,仅举一个例子)。FileSystemWatcher会注意到该文件并执行一些代码,而这些代码反过来会在同一目录中弹出一个*.csv。现在我知道这将重新触发观察者,它将陷入一个无限循环中——这是我第一次打算这么做

当此代码运行时,我在管理事件的处理程序代码中收到一个越界异常。值得注意的是,在处理Quartz作业和使用for循环时会导致此异常。foreach中不会发生异常

我意识到这段代码可能…很有趣,但有人能解释是什么导致for(范围越界异常)中的额外增量,以及迭代器为什么会成功吗

更新日期:美国东部时间2016年4月14日上午8:05 正如乔恩指出的,这只是一个简单的疏忽和睡眠不足。当任务执行时,i是共享资源

                var tl = new Task[pdList.Count];
                for (int i = 0; i < pdList.Count; i++)
                {
                    int li = i; // i is shared...use local copy
                                // use foreach instead
                    tl[i] = Task.Factory.StartNew(() => { ExecuteProcess(pdList[li], hargs); }, TaskCreationOptions.LongRunning);
                }
var tl=新任务[pdList.Count];
for(int i=0;i{ExecuteProcess(pdList[li],hargs);},TaskCreationOptions.longlunning);
}
更新日期:2016年4月14日美国东部时间上午7:09 根据Jon的指导,我将编写一段较小的代码,希望能够复制这个问题。同时,我添加了stacktrace和异常详细信息。整个项目在github上免费提供,网址为:

例外信息

索引超出范围。必须为非负数且小于 收藏。参数名称:索引

异常堆栈跟踪:

   at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at ThatIntegrationEngine.Engine.<>c__DisplayClass25_1.<BeginProcessExecution>b__0() in Z:\src\ThatIntegrationEngine\ThatIntegrationEngine.Core\Hood\Engine.cs:line 265
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
at System.ThrowHelper.throwargumentotofrangeexception(exception参数,exception资源)
位于System.Collections.Generic.List`1.get_项(Int32索引)
在Z:\src\ThatIntegrationEngine\ThatIntegrationEngine.Core\Hood\Engine.cs中的该IntegrationEngine.Engine.c_uu显示Class25_1.b_u0():第265行
在System.Threading.Tasks.Task.InnerInvoke()中
在System.Threading.Tasks.Task.Execute()中
任务线程内的Stacktrace调用:

   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at ThatIntegrationEngine.Engine.<>c__DisplayClass25_1.<BeginProcessExecution>b__0() in Z:\src\ThatIntegrationEngine\ThatIntegrationEngine.Core\Hood\Engine.cs:line 263
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   at System.Threading.Tasks.Task.ExecutionContextCallback(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
   at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
   at System.Threading.Tasks.ThreadPoolTaskScheduler.LongRunningThreadWork(Object obj)
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart(Object obj)
   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at ThatIntegrationEngine.Engine.<>c__DisplayClass25_1.<BeginProcessExecution>b__0() in Z:\src\ThatIntegrationEngine\ThatIntegrationEngine.Core\Hood\Engine.cs:line 263
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   at System.Threading.Tasks.Task.ExecutionContextCallback(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
   at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
   at System.Threading.Tasks.ThreadPoolTaskScheduler.LongRunningThreadWork(Object obj)
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart(Object obj)
Exception thrown: 'System.ArgumentOutOfRangeException' in mscorlib.dll
位于System.Environment.GetStackTrace(异常e,布尔needFileInfo)
在System.Environment.get_StackTrace()中
在Z:\src\ThatIntegrationEngine\ThatIntegrationEngine.Core\Hood\Engine.cs中的该IntegrationEngine.Engine.c\u显示Class25\u 1.b\u 0():第263行
在System.Threading.Tasks.Task.InnerInvoke()中
在System.Threading.Tasks.Task.Execute()中
位于System.Threading.Tasks.Task.ExecutionContextCallback(对象obj)
位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext、ContextCallback回调、对象状态、布尔值preserveSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔保存SyncCTX)
位于System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task和currentTaskSlot)
在System.Threading.Tasks.Task.ExecuteEntry(布尔bPreventDoubleExecution)
位于System.Threading.Tasks.ThreadPoolTaskScheduler.LongRunningThreadWork(对象obj)
位于System.Threading.ThreadHelper.ThreadStart\u上下文(对象状态)
位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext、ContextCallback回调、对象状态、布尔值preserveSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔保存SyncCTX)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
位于System.Threading.ThreadHelper.ThreadStart(对象obj)
位于System.Environment.GetStackTrace(异常e,布尔needFileInfo)
在System.Environment.get_StackTrace()中
在Z:\src\ThatIntegrationEngine\ThatIntegrationEngine.Core\Hood\Engine.cs中的该IntegrationEngine.Engine.c\u显示Class25\u 1.b\u 0():第263行
在System.Threading.Tasks.Task.InnerInvoke()中
在System.Threading.Tasks.Task.Execute()中
位于System.Threading.Tasks.Task.ExecutionContextCallback(对象obj)
位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext、ContextCallback回调、对象状态、布尔值preserveSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔保存SyncCTX)
位于System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task和currentTaskSlot)
在System.Threading.Tasks.Task.ExecuteEntry(布尔bPreventDoubleExecution)
位于System.Threading.Tasks.ThreadPoolTaskScheduler.LongRunningThreadWork(对象obj)
位于System.Threading.ThreadHelper.ThreadStart\u上下文(对象状态)
位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext、ContextCallback回调、对象状态、布尔值preserveSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔保存SyncCTX)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
位于System.Threading.ThreadHelper.ThreadStart(对象obj)
引发异常:mscorlib.dll中的“System.ArgumentOutOfRangeException”
代码流:

石英触发器触发时引发的事件:

protected virtual void OnTimedActionAsync(object s, CronSchedulerEventArgs e)
{
    EventHandler<CronSchedulerEventArgs> handler = TimedActionAsync;
    handler?.BeginInvoke(this, e, cs =>
    {
        var delg = (EventHandler<CronSchedulerEventArgs>)cs.AsyncState;
        delg.EndInvoke(cs);
    },
    handler);
}
受保护的虚拟void OnTimedActionAsync(对象s、CronSchedulerEventArgs e)
{
EventHandler=TimedActionAsync;
处理程序?.BeginInvoke(此,e,c
protected virtual void OnCreatedAsync(object sender, FileSystemEventArgs args)
{
    EventHandler<DirWatcherEventArgs> handler = FileArrivedAsync;
    handler?.BeginInvoke(this, new DirWatcherEventArgs(args.FullPath, WatcherChangeTypes.Created, Id, Name)
    , cs =>
        {
            var delg = (EventHandler<DirWatcherEventArgs>)cs.AsyncState;
            delg.EndInvoke(cs);
        }
    , handler);
}
    private void HandleScheduledActionAsync(object sender, CronSchedulerEventArgs csarg)
    {
        var scheduler = sender as ICronScheduler;
        if (scheduler != null)
        {
            // load process type based on trigger (sender) id
            // dynamically create instance of the process and pass 
            // all expected information
            BeginProcessExecution(csarg);
        }
    }

    private void HandleFileArrivalAsync(object sender, DirWatcherEventArgs dwargs)
    {
        var watcher = sender as IDirectoryWatcher;
        if (watcher != null)
        {
            // load process type based on trigger (sender) id
            // dynamically create instance of the process and pass 
            // all expected information
            BeginProcessExecution(dwargs);
        }
    }

    private void BeginProcessExecution(HandlerEventArgs hargs)
    {
        IList<IProcessDetails> pdList = null;

        if (this._processHandlerRelation.TryGetValue(hargs.TriggerId, out pdList))
        {
            if (pdList.Count > 1)
            {
                try
                {
                    //!!! FAILURE !!!  
                    //this fails with out of range exception
                    var tl = new Task[pdList.Count];
                    for(int i = 0; i < pdList.Count; i++)
                    {
                        //!!! EXCEPTION !!!  
                        // this causes an out of range exception
                        // at exec task is attempting to read final value of i                           
                        // is i accessed by ref? -- no it's a shared resource
                        tl[i] = Task.Factory.StartNew(() => ExecuteProcess(pdList[i], hargs), TaskCreationOptions.LongRunning);
                    }

                    //this does not cause an exception
                    //var tl = new List<Task>();
                    //foreach (var pd in pdList)
                    //{
                    //    tl.Add(Task.Factory.StartNew(() => ExecuteProcess(pd, hargs), TaskCreationOptions.LongRunning));
                    //}

                    Task.WaitAll(tl);

                    // this does not cause an exception
                    //Parallel.ForEach(pdList, pd => ExecuteProcess(pd, hargs));                     
                }
                catch (Exception e)
                {
                    // log exception
                }
            }
            else
            {// avoid parallelization if only one process is expected 
             // to be executed
                // execute on calling thread
                ExecuteProcess(pdList[0], hargs);
            }
        }
    }
            var tl = new Task[pdList.Count];
            for (int i = 0; i < pdList.Count; i++)
            {
                int li = i; // i is shared...use local copy
                            // use foreach instead
                tl[i] = Task.Factory.StartNew(() => ExecuteProcess(pdList[li], hargs), TaskCreationOptions.LongRunning);
            }
                    int pi = 0;    
                    var plist = new Task[pdList.Count];                        
                    foreach(var pd in pdList)
                    {
                        plist[pi++] = Task.Factory.StartNew(() => ExecuteProcess(pd, hargs), TaskCreationOptions.LongRunning);
                    }

                    Task.WaitAll(plist);