2013-05-30 26 views
1

在Form1頂部我所做的:我在一個計時器滴答事件中使用位圖,一切都很慢,我該如何解決它?

private volatile bool _workersEnabled; 
private ConcurrentQueue<Bitmap> _imageBuffer; 
Thread threadA; 
Thread threadB; 

然後在構造函數中:

_workersEnabled = false; 
_imageBuffer = new ConcurrentQueue<Bitmap>(); 

threadA = new Thread(CaptureScreensEntryPoint); 
threadB = new Thread(ConsumeScreensEntryPoint); 

然後在按鈕單擊事件:

private void StartRecording_Click(object sender, EventArgs e) 
{ 
    ffmp.Start("test.avi", 25); 
    _workersEnabled = true; 
    threadA.Start(); 
    threadA.Start(); 

    //Disable the button, so we eliminate the possibility to start this twice (would throw an exception anyway). 
    StartRecording.Enabled = false; 
} 

然後之後我說:

private void CaptureScreensEntryPoint() 
{ 
    while(_workersEnabled) 
    { 
     Bitmap bitmap = (Bitmap)ScreenCapture.CaptureScreen(true); 

     //Just add it to the queue. 
     _imageBuffer.Enqueue(bitmap); 

     //Wait a bit 
     Thread.Sleep(40); 
    } 
} 

private void ConsumeScreensEntryPoint() 
{ 
    while (_workersEnabled) 
    { 
     Bitmap workItem = null; 
     if (_imageBuffer.TryDequeue(out workItem)) 
     { 
      ffmp.PushFrame(workItem); 
      workItem.Dispose(); 
     } 

     //Also wait a bit here. Don't want to eat up the entire processor. 
     Thread.Sleep(10); 
    } 
} 

例外是threadA.Start();

ThreadStateException:線程正在運行或終止;它不能重新啓動

System.Threading.ThreadStateException was unhandled 
    HResult=-2146233056 
    Message=Thread is running or terminated; it cannot restart. 
    Source=mscorlib 
    StackTrace: 
     at System.Threading.Thread.StartupSetApartmentStateInternal() 
     at System.Threading.Thread.Start(StackCrawlMark& stackMark) 
     at System.Threading.Thread.Start() 
     at ScreenVideoRecorder.Form1.StartRecording_Click(Object sender, EventArgs e) in d:\C-Sharp\ScreenVideoRecorder\ScreenVideoRecorderWorkingVersion\Form1.cs:line 152 
     at System.Windows.Forms.Control.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnClick(EventArgs e) 
     at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
     at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
     at System.Windows.Forms.Button.WndProc(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.Run(Form mainForm) 
     at ScreenVideoRecorder.Program.Main() in d:\C-Sharp\ScreenVideoRecorder\ScreenVideoRecorderWorkingVersion\Program.cs:line 18 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     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() 
    InnerException: 

我怎樣才能解決呢?

+1

是的,在工作線程上執行它。讓它異步推動框架。您可能還想將幀請求推送到工作線程中的隊列中,並讓它執行它的工作(當有事情要做時)。 –

+0

marceln你能告訴我一個例子如何做到背景工作者和隊列或沒有隊列嗎? –

+0

請參閱下面的答案。這不是一個後臺工作者,它更簡單一些。 –

回答

0

嘗試將捕獲代碼放在單獨的線程中。我爲桌面捕捉應用程序做了類似的事情,並且能夠獲得大約60個FPS的。

1

我不確定哪一個需要更長的時間:ScreenCapture.CaptureScreenffmp.PushFrame(bitmap)。由於它是一個位圖,我假設ffmp不能那麼快,而且它會吃掉一段時間。

我會採取生產者/消費者的方法。你有線程A做屏幕截圖,將它們推到ConcurrentQueue,然後從線程B將它們推送到ffmp。

一些示例代碼(沒有測試過,也不保證被全面工作,所以可能是你必須做一些調整):

//We need this thread for cross-thread access, so we don't want it cached. 
private volatile bool _workersEnabled; 
private ConcurrentQueue<Bitmap> _imageBuffer; 

public Form1() 
{ 
    InitializeComponent(); 
    ffmp = new Ffmpeg(); 
    sc = new ScreenCapture(); 

    _workersEnabled = false; 
    _imageBuffer = new ConcurrentQueue<Bitmpap>(); 

    threadA = new Thread(CaptureScreensEntryPoint); 
    threadB = new Thread(ConsumeScreensEntryPoint); 
} 

private void StartRecording_Click(object sender, EventArgs e) 
{ 
    _workersEnabled = true; 
    threadA.Start(); 
    threadB.Start(); 

    //Disable the button, so we eliminate the possibility to start this twice (would throw an exception anyway). 
    StartRecording.Enabled = false; 
} 

private void CaptureScreensEntryPoint() 
{ 
    while(_workersEnabled) 
    { 
    Bitmap bitmap = (Bitmap)ScreenCapture.CaptureScreen(true); 

    //just add it to the queue. 
    _imageBuffer.Enqueue(bitmap); 

    //wait a bit 
    Thread.Sleep(40); 
    } 
} 

private void ConsumeScreensEntryPoint() 
{ 
    while(_workersEnabled) 
    { 
    Bitmap workItem = null; 
    if(_imageBuffer.TryDequeue(out workItem)) 
    { 
     ffmp.PushFrame(workItem); 
     workItem.Dispose(); 
    } 

    //Also wait a bit here. Don't want to eat up the entire processor. 
    Thread.Sleep(10); 
    } 
} 

務必將_workersEnabledfalse當你想停止工作人員,例如當表格關閉時,或者您有專門的按鈕。您可能還想添加一些錯誤處理,併爲兩個線程配置睡眠週期。


注意

我想我可能已經與第三方物流完成的,但,這是稍快張貼。隨意調整解決方案或發佈一個新的。

+0

marceln我在threadA.Start()上收到錯誤;線。現在我會更新我的問題,請拿起戰利品。 –

相關問題