/// <summary> /// /// </summary> /// <see cref="IRunnable.Start()" /> public void Start() { lock (this._SYNC) { if (this.IsRunning) { return; } this.DisposeOldTask(); try { var newCancelSrc = new CancellationTokenSource(); var newTask = new Task(action: this.TaskAction, cancellationToken: newCancelSrc.Token, creationOptions: TaskCreationOptions.LongRunning); this._cancelSource = newCancelSrc; this._queue = new SyncJobActionQueue(); this.State = SyncJobState.Running; newTask.Start(); this._task = newTask; } catch { this.DisposeOldTask(); throw; } } }
private void DisposeOldTask() { using (var t = this._task) { if (t != null) { var cs = this._cancelSource; if (cs != null) { cs.Cancel(); } t.Wait(); } } this._queue = null; this._task = null; this._cancelSource = null; this.State = SyncJobState.Stopped; }
private void TaskAction() { var cancelSrc = this._cancelSource; if (cancelSrc == null) { return; } var queue = this._queue; if (queue == null) { return; } var ctx = new SyncJobExeuctionContext() { CancelSource = cancelSrc, DestionationDirectory = Path.GetFullPath(this.DestinationDirectory), Job = this, LogAction = this.Log, ProgressChangedHandler = this.OnProgressChanged, Queue = queue, SourceDirectory = Path.GetFullPath(this.SourceDirectory), SyncRoot = new object(), }; bool retry; do { retry = false; try { this.State = SyncJobState.Running; // now using (var srcWatcher = new FileSystemWatcher()) { FileSystemEventHandler srcFsHandler = null; RenamedEventHandler srcRenameHandler = null; ErrorEventHandler srcErrHandler = null; try { // setup 'srcWatcher' { srcFsHandler = this.CreateFileSystemEventHandlerForSource(ctx); srcRenameHandler = new RenamedEventHandler(srcFsHandler); srcErrHandler = (sender, e) => { retry = true; }; SetupFileSystemWatcher(watcher: srcWatcher, handler: srcFsHandler, renameHandler: srcRenameHandler, errorHandler: srcErrHandler); srcWatcher.Path = ctx.SourceDirectory; srcWatcher.IncludeSubdirectories = true; } Action initalSync; this.InitalSyncAction = initalSync = () => { ctx.RaiseProgressChanged(text: "Start inital sync..."); srcFsHandler(srcWatcher, new FileSystemEventArgs(WatcherChangeTypes.Changed, srcWatcher.Path, null)); }; lock (ctx.SyncRoot) { srcWatcher.EnableRaisingEvents = true; initalSync(); } // now watch for sync actions this.HandleSyncActions(srcWatcher, ctx); } finally { lock (ctx.SyncRoot) { srcWatcher.EnableRaisingEvents = false; } DisposeFileSystemWatcher(watcher: srcWatcher, handler: srcFsHandler, renameHandler: srcRenameHandler, errorHandler: srcErrHandler); } } if (ctx.CancelSource.IsCancellationRequested) { this.State = SyncJobState.Canceled; } else { this.State = SyncJobState.Finished; } } catch { this.State = SyncJobState.Faulted; } finally { this.InitalSyncAction = null; if (retry) { cancelSrc.Cancel(); } } }while (retry); }