C# 如何以异步方式运行NamedPipeServerStream?

C# 如何以异步方式运行NamedPipeServerStream?,c#,winforms,C#,Winforms,如何以异步方式运行NamedPipeServerStream 我没有通过服务器在另一台计算机上使用管道。我只在我的电脑上使用它。代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using System.IO.Pipes; using System.Runtim

如何以异步方式运行NamedPipeServerStream

我没有通过服务器在另一台计算机上使用管道。我只在我的电脑上使用它。代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.IO.Pipes;
using System.Runtime.InteropServices;

namespace ScreenVideoRecorder
{
    class Ffmpeg
    {
        NamedPipeServerStream p;
        String pipename = "mytestpipe";
        byte[] b;
        //int i, j;
        System.Diagnostics.Process process;

        public Ffmpeg()
        {

        }

        public void Start(string FileName, int BitmapRate )
        {
            p = new NamedPipeServerStream(pipename, PipeDirection.Out, 1, PipeTransmissionMode.Byte);
            b = new byte[1920 * 1080 * 3]; // Some buffer for the R, G and B of pixels of an image of size 720p.
            process = new System.Diagnostics.Process();
            process.StartInfo.FileName = @"D:\pipetest\pipetest\ffmpegx86\ffmpeg.exe";
            process.EnableRaisingEvents = false;
            process.StartInfo.WorkingDirectory = @"D:\pipetest\pipetest\ffmpegx86";
            process.StartInfo.Arguments = @"-f rawvideo -pix_fmt bgr0 -video_size 1920x1080 -i \\.\pipe\mytestpipe -map 0 -c:v libx264 -r " + BitmapRate + " " + FileName;
            process.Start();

            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = false;
            p.WaitForConnection();
        }
一切正常。问题是当进程启动时,我看到命令提示符窗口,并看到窗口中的所有工作。我去不了表格。我可以在屏幕上拖动/移动命令提示窗口,但我无法到达窗体窗口以单击按钮或停止操作。我需要等待它首先完成在命令提示符窗口或进程窗口中的工作

使用下面的代码行,我看到了变量p的一个属性,以检查它是否异步,但如何将其设置为异步呢

p.IsAsync
我试图找到一些例子,但它们都是根据两台计算机之间的服务器提供的,我认为它们都带有安全功能

后来,我更改了这一行:

p = new NamedPipeServerStream(pipename, PipeDirection.Out, 1, PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
最后添加:PipeOptions.Asynchronous

现在,当我运行我的应用程序时,我遇到了一个异常:

p.Write(rgbValues, 0, length);
例外情况:

InvalidoPerctionException:管道尚未连接

这是我所有更改的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.IO.Pipes;
using System.Runtime.InteropServices;

namespace ScreenVideoRecorder
{
    class Ffmpeg
    {
        NamedPipeServerStream p;
        String pipename = "mytestpipe";
        byte[] b;
        //int i, j;
        System.Diagnostics.Process process;
        IAsyncResult ar;

        public Ffmpeg()
        {

        }

        public void Start(string FileName, int BitmapRate )
        {
            p = new NamedPipeServerStream(pipename, PipeDirection.Out, 1, PipeTransmissionMode.Byte,PipeOptions.Asynchronous);
            b = new byte[1920 * 1080 * 3]; // Some buffer for the R G and B of pixels of an image of size 720p.
            process = new System.Diagnostics.Process();
            process.StartInfo.FileName = @"D:\pipetest\pipetest\ffmpegx86\ffmpeg.exe";
            process.EnableRaisingEvents = false;
            process.StartInfo.WorkingDirectory = @"D:\pipetest\pipetest\ffmpegx86";
            process.StartInfo.Arguments = @"-f rawvideo -pix_fmt bgr0 -video_size 1920x1080 -i \\.\pipe\mytestpipe -map 0 -c:v libx264 -r " + BitmapRate + " " + FileName;
            process.Start();

            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = false;
            ar = p.BeginWaitForConnection(EndWait,null);
        }

        void EndWait(IAsyncResult iar)
        {
            var state = ar.AsyncState; //fetch result, mandatory!
        }

        public void PushFrame(Bitmap bmp)
        {
            int length;
            // Lock the bitmap's bits.
            //bmp = new Bitmap(1920, 1080);
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            //Rectangle rect = new Rectangle(0, 0, 1280, 720);
            System.Drawing.Imaging.BitmapData bmpData =
                bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
                bmp.PixelFormat);

            int absStride = Math.Abs(bmpData.Stride);
            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            //length = 3 * bmp.Width * bmp.Height;
            length = absStride * bmpData.Height;
            byte[] rgbValues = new byte[length];

            //Marshal.Copy(ptr, rgbValues, 0, length);
            int j = bmp.Height - 1;
            for (int i = 0; i < bmp.Height; i++)
            {
                IntPtr pointer = new IntPtr(bmpData.Scan0.ToInt32() + (bmpData.Stride * j));
                System.Runtime.InteropServices.Marshal.Copy(pointer, rgbValues, absStride * (bmp.Height - i - 1), absStride);
                j--;
            }

            p.Write(rgbValues, 0, length);
            bmp.UnlockBits(bmpData);
当您使用当前线程时,该线程将被阻止,直到操作完成。
您可以使用创建在后台工作的线程。
使用返回的
IAsyncResult
,可以获取异步操作的结果

发件人:

IAsyncResult接口由包含可以异步操作的方法的类实现。它是启动异步操作的方法的返回类型,如
FileStream.BeginRead
,并传递给结束异步操作的方法,如
FileStream.EndRead
<当异步操作完成时,code>IAsyncResult对象也被传递给
AsyncCallback
委托调用的方法。 支持
IAsyncResult
接口的对象存储异步操作的状态信息,并提供同步对象,以允许在操作完成时向线程发送信号



bash.d p.BeginWaitForConnection需要一些东西。你为什么要做p.BeginWaitForConnection(它要求异步回调,对象状态)我该怎么办?Bash好的,我正在更新我的问题,但我现在得到的是一个例外。oops错误地更新了你的答案。但这是我得到的例外。好的,这次更新我的问题时,我更改了一些内容,但仍然不起作用。在调用
BeginWaitForConnection
后,您需要确保已首先连接。等待
EndWait
首先出现。
System.InvalidOperationException was unhandled
  HResult=-2146233079
  Message=Pipe hasn't been connected yet.
  Source=System.Core
  StackTrace:
       at System.IO.Pipes.PipeStream.CheckWriteOperations()
       at System.IO.Pipes.PipeStream.Write(Byte[] buffer, Int32 offset, Int32 count)
       at ScreenVideoRecorder.Ffmpeg.PushFrame(Bitmap bmp) in d:\C-Sharp\ScreenVideoRecorder\ScreenVideoRecorderWorkingVersion\Ffmpeg.cs:line 77
       at ScreenVideoRecorder.Form1.StartRecording_Click(Object sender, EventArgs e) in d:\C-Sharp\ScreenVideoRecorder\ScreenVideoRecorderWorkingVersion\Form1.cs:line 53
       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:
class Ffmpeg
{
    NamedPipeServerStream p;
    String pipename = "mytestpipe";
    byte[] b;
    //int i, j;
    System.Diagnostics.Process process;
    IAsyncResult ar;

    public Ffmpeg()
    {

    }

    public void Start(string FileName, int BitmapRate )
    {
        p = new NamedPipeServerStream(pipename, PipeDirection.Out, 1, PipeTransmissionMode.Byte);
        b = new byte[1920 * 1080 * 3]; // some buffer for the r g and b of pixels of an image of size 720p 
        process = new System.Diagnostics.Process();
        process.StartInfo.FileName = @"D:\pipetest\pipetest\ffmpegx86\ffmpeg.exe";
        process.EnableRaisingEvents = false;
        process.StartInfo.WorkingDirectory = @"D:\pipetest\pipetest\ffmpegx86";
        process.StartInfo.Arguments = @"-f rawvideo -pix_fmt bgr0 -video_size 1920x1080 -i \\.\pipe\mytestpipe -map 0 -c:v libx264 -r " + BitmapRate + " " + FileName;
        process.Start();

        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = false;
        ar = p.BeginWaitForConnection(EndWait, null);
    }

//callback when client connects
void EndWait(IAsyncResult iar){
    var state = iar.AsyncState; // fetch state -> cast to desired type
    //do something when client connected
}