patterncsharpMinor
SharpDX ScreenCapture
Viewed 0 times
screencapturesharpdxstackoverflow
Problem
I'm currently working on a monitor screen capture with C# and the SharpDX library. The code works and allow recording bitmap screenshots (dynamically for DirectX 11 games and desktop) in a loop.
But I have a little performance problem in my loop and I'm trying to get 60 records per second at least (I reach 40 records/sec max on my computer).
As you can see, I was tried to use
I hope that my project will be useful to you and it would be great if someone would have some optimizations to suggest to me.
```
class DXCapture
{
PictureBox pictureBox;
bool ready = false;
bool Recording = false;
Task RecordingTask;
int saveSizeX;
int saveSizeY;
int width;
int height;
int numAdapter;
int numOutput;
Factory1 factory;
Adapter1 adapter;
SharpDX.Direct3D11.Device device;
Output output;
Output1 output1;
Texture2DDescription texture2DDescription;
Texture2D screenTexture;
OutputDuplication duplicatedOutput;
SharpDX.DXGI.Resource screenResource;
public DXCapture(PictureBox pictureBox, BenchMark bench, int sizeX = 1920, int sizeY = 1080, int numAdapter = 0, int numOutput = 0)
{
this.pictureBox = pictureBox;
this.saveSizeX = sizeX;
this.saveSizeY = sizeY;
this.numAdapter = numAdapter;
this.numOutput = numOutput;
this.bench = bench;
InitDX();
}
public void InitDX()
{
try
{
factory = new SharpDX.DXGI.Factory1();
adapter = factory.GetAdapter1(numAdapter);
device = new SharpDX.Direct3D11.Device(adapter);
output = adapter.GetOutput(numOutput);
output1 = output.QueryInterface();
// Width/Height of desktop to capture
width = output.Description.DesktopBounds.Left + output.Description.DesktopBounds.Right;
height = output.Description.Deskto
But I have a little performance problem in my loop and I'm trying to get 60 records per second at least (I reach 40 records/sec max on my computer).
As you can see, I was tried to use
Tasks to perform this but it's not enough and I'm not an expert in parallel programming.I hope that my project will be useful to you and it would be great if someone would have some optimizations to suggest to me.
```
class DXCapture
{
PictureBox pictureBox;
bool ready = false;
bool Recording = false;
Task RecordingTask;
int saveSizeX;
int saveSizeY;
int width;
int height;
int numAdapter;
int numOutput;
Factory1 factory;
Adapter1 adapter;
SharpDX.Direct3D11.Device device;
Output output;
Output1 output1;
Texture2DDescription texture2DDescription;
Texture2D screenTexture;
OutputDuplication duplicatedOutput;
SharpDX.DXGI.Resource screenResource;
public DXCapture(PictureBox pictureBox, BenchMark bench, int sizeX = 1920, int sizeY = 1080, int numAdapter = 0, int numOutput = 0)
{
this.pictureBox = pictureBox;
this.saveSizeX = sizeX;
this.saveSizeY = sizeY;
this.numAdapter = numAdapter;
this.numOutput = numOutput;
this.bench = bench;
InitDX();
}
public void InitDX()
{
try
{
factory = new SharpDX.DXGI.Factory1();
adapter = factory.GetAdapter1(numAdapter);
device = new SharpDX.Direct3D11.Device(adapter);
output = adapter.GetOutput(numOutput);
output1 = output.QueryInterface();
// Width/Height of desktop to capture
width = output.Description.DesktopBounds.Left + output.Description.DesktopBounds.Right;
height = output.Description.Deskto
Solution
Console.WriteLine("Error GetShot ACCESS LOST - relaunch in 2s !");
Thread.Sleep(2000);This second line might be killing the performance but even if it's hit only occasionally it's usually a bad practice.
Thread.Sleep is blocking a thread completely. Nothing else can be handled by it during the wait period. You are using Tasks in other places so try to use a Task.Delay here or even better a timer that will trigger a relaunch.Thread.Sleep(2000);
DisposeDX();
GC.Collect();
InitDX();I also think you should dispose everything right away and then wait if necessary.
You could also try to make the
GetShot method a real async one by changing its signature toprivate async Task GetShot()this will allow you to wait like this
Console.WriteLine("Error GetShot ACCESS LOST - relaunch in 2s !");
await Task.Delay(TimeSpan.FromSeconds(2000));or to replace
Task.Factory.StartNew(() =>with
await Task.Run(() =>which is actaully a shortcut for the
StartNew where you add the await keyword.You'll also need to adjust the
StartRecord method to something like this:public void StartRecord(int limitFPS = 0)
{
if (!Recording)
{
Recording = true;
RecordingTask = Task.Run(async () =>
{
while (Recording)
{
await GetShot();
}
});
RecordingTask.Start();
}
}Code Snippets
Console.WriteLine("Error GetShot ACCESS LOST - relaunch in 2s !");
Thread.Sleep(2000);Thread.Sleep(2000);
DisposeDX();
GC.Collect();
InitDX();private async Task GetShot()Console.WriteLine("Error GetShot ACCESS LOST - relaunch in 2s !");
await Task.Delay(TimeSpan.FromSeconds(2000));Task.Factory.StartNew(() =>Context
StackExchange Code Review Q#162536, answer score: 4
Revisions (0)
No revisions yet.