private void ExecuteExports() { byte[] fileData = m_fileData; if (m_enabled && (object)fileData != null && m_exportDestinations.Count > 0) { string fileName = null; ExportState[] exportStates = null; ExportDestination[] destinations; try { // Get a temporary file name fileName = Path.GetTempFileName(); // Export data to the temporary file File.WriteAllBytes(fileName, fileData); lock (m_exportDestinationsLock) { // Cache a local copy of export destinations to reduce lock time destinations = m_exportDestinations.ToArray(); } // Define a new export state for each export destination exportStates = new ExportState[destinations.Length]; for (int i = 0; i < exportStates.Length; i++) { exportStates[i] = new ExportState { SourceFileName = fileName, DestinationFileName = destinations[i].DestinationFile }; } // Spool threads to attempt copy of export files for (int i = 0; i < destinations.Length; i++) { ThreadPool.QueueUserWorkItem(CopyFileToDestination, exportStates[i]); } // Wait for exports to complete - even if user specifies to wait indefinitely spooled copy routines // will eventually return since there is a specified maximum retry count if (!exportStates.Select(exportState => exportState.WaitHandle).WaitAll(m_exportTimeout)) { // Exports failed to complete in specified allowed time, set timeout flag for each export state Array.ForEach(exportStates, exportState => exportState.Timeout = true); OnStatusMessage("Timed out attempting export, waited for {0}.", Ticks.FromMilliseconds(m_exportTimeout).ToElapsedTimeString(2).ToLower()); } } catch (Exception ex) { OnProcessException(new InvalidOperationException($"Exception encountered during export preparation: {ex.Message}", ex)); } finally { // Dispose the export state wait handles if ((object)exportStates != null) { foreach (ExportState exportState in exportStates) { exportState.Dispose(); } } // Delete the temporary file - wait for the specified retry time in case the export threads may still be trying // their last copy attempt. This is important if the timeouts are synchronized and there is one more export // about to be attempted before the timeout flag is checked. new Action(() => DeleteTemporaryFile(fileName)).DelayAndExecute(m_retryDelayInterval); } } }
private void ExecuteExports(object state) { // Outer try/finally is used only to make sure m_exportInProgress state is reset regardless of success or failure of export try { // Dereference file bytes to be exported byte[] fileData = state as byte[]; if (m_enabled && (object)fileData != null) { string filename = null; ExportState[] exportStates = null; ExportDestination[] destinations; try { // Get a temporary file name filename = Path.GetTempFileName(); // Export data to the temporary file File.WriteAllBytes(filename, fileData); lock (this) { // Cache a local copy of export destinations to reduce lock time destinations = m_exportDestinations.ToArray(); } // Define a new export state for each export destination exportStates = new ExportState[destinations.Length]; for (int i = 0; i < exportStates.Length; i++) { exportStates[i] = new ExportState() { SourceFileName = filename, DestinationFileName = destinations[i].DestinationFile }; } // Spool threads to attempt copy of export files for (int i = 0; i < destinations.Length; i++) { ThreadPool.QueueUserWorkItem(CopyFileToDestination, exportStates[i]); } // Wait for exports to complete - even if user specifies to wait indefinitely spooled copy routines // will eventually return since there is a specified maximum retry count if (!WaitHandle.WaitAll(exportStates.Select(exportState => exportState.WaitHandle).ToArray(), m_exportTimeout)) { // Exports failed to complete in specified allowed time, set timeout flag for each export state Array.ForEach(exportStates, exportState => exportState.Timeout = true); OnStatusMessage("Timed out attempting export, waited for {0}.", Ticks.FromMilliseconds(m_exportTimeout).ToElapsedTimeString(2).ToLower()); } } catch (ThreadAbortException) { throw; // This exception is normal, we'll just rethrow this back up the try stack } catch (Exception ex) { OnProcessException(new InvalidOperationException(string.Format("Exception encountered during export preparation: {0}", ex.Message), ex)); } finally { // Dispose the export state wait handles if ((object)exportStates != null) { foreach (ExportState exportState in exportStates) { exportState.Dispose(); } } // Delete the temporary file - we queue this up in case the export threads may still be trying their last copy attempt ThreadPool.QueueUserWorkItem(DeleteTemporaryFile, filename); } } } finally { // Synchronously reset export progress state lock (m_exportInProgressLock) { m_exportInProgress = false; } } }
private void ExecuteExports() { byte[] fileData = m_fileData; if (m_enabled && (object)fileData != null && m_exportDestinations.Count > 0) { string fileName = null; ExportState[] exportStates = null; ExportDestination[] destinations; try { // Get a temporary file name fileName = Path.GetTempFileName(); // Export data to the temporary file File.WriteAllBytes(fileName, fileData); lock (m_exportDestinationsLock) { // Cache a local copy of export destinations to reduce lock time destinations = m_exportDestinations.ToArray(); } // Define a new export state for each export destination exportStates = new ExportState[destinations.Length]; for (int i = 0; i < exportStates.Length; i++) { exportStates[i] = new ExportState { SourceFileName = fileName, DestinationFileName = destinations[i].DestinationFile }; } // Spool threads to attempt copy of export files for (int i = 0; i < destinations.Length; i++) ThreadPool.QueueUserWorkItem(CopyFileToDestination, exportStates[i]); // Wait for exports to complete - even if user specifies to wait indefinitely spooled copy routines // will eventually return since there is a specified maximum retry count if (!exportStates.Select(exportState => exportState.WaitHandle).WaitAll(m_exportTimeout)) { // Exports failed to complete in specified allowed time, set timeout flag for each export state Array.ForEach(exportStates, exportState => exportState.Timeout = true); OnStatusMessage("Timed out attempting export, waited for {0}.", Ticks.FromMilliseconds(m_exportTimeout).ToElapsedTimeString(2).ToLower()); } } catch (Exception ex) { OnProcessException(new InvalidOperationException($"Exception encountered during export preparation: {ex.Message}", ex)); } finally { // Dispose the export state wait handles if ((object)exportStates != null) { foreach (ExportState exportState in exportStates) exportState.Dispose(); } // Delete the temporary file - wait for the specified retry time in case the export threads may still be trying // their last copy attempt. This is important if the timeouts are synchronized and there is one more export // about to be attempted before the timeout flag is checked. new Action(() => DeleteTemporaryFile(fileName)).DelayAndExecute(m_retryDelayInterval); } } }