123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- 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 WechatPCMsgBakTool.Helpers
- {
- public class ToolsHelper
- {
- public 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 "";
- }
- }
- public 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<Task> _tasks = new LinkedList<Task>(); // 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<Task> GetScheduledTasks()
- {
- bool lockTaken = false;
- try
- {
- Monitor.TryEnter(_tasks, ref lockTaken);
- if (lockTaken) return _tasks;
- else throw new NotSupportedException();
- }
- finally
- {
- if (lockTaken) Monitor.Exit(_tasks);
- }
- }
- }
- }
|