using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace WechatBakTool.Helpers { public class ToolsHelper { private static TaskFactory factory = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(10)); public static string DecodeVoice(string source,string pcm,string to) { string ffmpeg = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tools", "ffmpeg.exe"); string silk_decoder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tools", "silk_v3_decoder.exe"); Task task = factory.StartNew(() => { Process silk = new Process(); silk.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; silk.StartInfo.UseShellExecute = false; silk.StartInfo.CreateNoWindow = true; silk.StartInfo.FileName = silk_decoder; silk.StartInfo.Arguments = string.Format("\"{0}\" \"{1}\"", source, pcm); silk.Start(); silk.WaitForExit(); if (File.Exists(pcm)) { Process ff = new Process(); ff.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; ff.StartInfo.UseShellExecute= false; ff.StartInfo.CreateNoWindow = true; ff.StartInfo.FileName = ffmpeg; ff.StartInfo.Arguments = string.Format(" -y -f s16le -ar 24000 -ac 1 -i \"{0}\" -ar 24000 -b:a 320k \"{1}\"", pcm, to); ff.Start(); ff.WaitForExit(); } }); return ""; } } partial class LimitedConcurrencyLevelTaskScheduler : TaskScheduler { // Indicates whether the current thread is processing work items. [ThreadStatic] private static bool _currentThreadIsProcessingItems; // The list of tasks to be executed private readonly LinkedList _tasks = new LinkedList(); // protected by lock(_tasks) // The maximum concurrency level allowed by this scheduler. private readonly int _maxDegreeOfParallelism; // Indicates whether the scheduler is currently processing work items. private int _delegatesQueuedOrRunning = 0; // Creates a new instance with the specified degree of parallelism. public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism) { if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism"); _maxDegreeOfParallelism = maxDegreeOfParallelism; } // Queues a task to the scheduler. protected sealed override void QueueTask(Task task) { // Add the task to the list of tasks to be processed. If there aren't enough // delegates currently queued or running to process tasks, schedule another. lock (_tasks) { _tasks.AddLast(task); if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism) { ++_delegatesQueuedOrRunning; NotifyThreadPoolOfPendingWork(); } } } // Inform the ThreadPool that there's work to be executed for this scheduler. private void NotifyThreadPoolOfPendingWork() { ThreadPool.UnsafeQueueUserWorkItem(_ => { // Note that the current thread is now processing work items. // This is necessary to enable inlining of tasks into this thread. _currentThreadIsProcessingItems = true; try { // Process all available items in the queue. while (true) { Task item; lock (_tasks) { // When there are no more items to be processed, // note that we're done processing, and get out. if (_tasks.Count == 0) { --_delegatesQueuedOrRunning; break; } // Get the next item from the queue item = _tasks.First.Value; _tasks.RemoveFirst(); } // Execute the task we pulled out of the queue base.TryExecuteTask(item); } } // We're done processing items on the current thread finally { _currentThreadIsProcessingItems = false; } }, null); } // Attempts to execute the specified task on the current thread. protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { // If this thread isn't already processing a task, we don't support inlining if (!_currentThreadIsProcessingItems) return false; // If the task was previously queued, remove it from the queue if (taskWasPreviouslyQueued) // Try to run the task. if (TryDequeue(task)) return base.TryExecuteTask(task); else return false; else return base.TryExecuteTask(task); } // Attempt to remove a previously scheduled task from the scheduler. protected sealed override bool TryDequeue(Task task) { lock (_tasks) return _tasks.Remove(task); } // Gets the maximum concurrency level supported by this scheduler. public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } } // Gets an enumerable of the tasks currently scheduled on this scheduler. protected sealed override IEnumerable GetScheduledTasks() { bool lockTaken = false; try { Monitor.TryEnter(_tasks, ref lockTaken); if (lockTaken) return _tasks; else throw new NotSupportedException(); } finally { if (lockTaken) Monitor.Exit(_tasks); } } } }