2017-12-07 11 views
0

私は非同期プロセスを理解し始めましたが、 に問題が発生しました。大量の異なる関数呼び出しで非同期を理解しようとしています

目的は:charのデータを取得してから、そのデータを使用します(私の場合はボタンのテキストとして使用します)。下に固定されているコードは非常に遅いです。最も遅い瞬間はデータです。実際にはget(int id)関数はインターネットからWinInet(同期的に)のデータを読み込み、Postメソッドを送信して答えを返します。

void some_func() 
{ 
for(int i(0);i<10;i++) 
    for(int q(0);q<5;q++) 
    { 
     char data[100]; 
     strcpy(data, get(i,q)); // i, q - just some identifier data 

     button[5*i+(q+1)]=new Button(data); 
    } 
} 

最初の質問:

getは、インターネットとは何の関係もありませんが、遅い実行されている場合、私は意味、generaly)それが解決されなければならない方法は?私は唯一の、愚かなアイデアを持っています:実行するgetすべてのスレッドで。それが正しい方法なら、どうしたらいいですか?なぜなら、それぞれのget関数から50スレッドの呼び出しを作成したからです。 50 getは機能しますか?

2番目の質問

WinInetとそれを実現するには?赤いMSDNがありますが、それは私にとってはあまりにも難しいです。ないローカル関数の変数が、オブジェクトのメンバオブジェクトに必須の参照カウントでなければならない現在のケースiq中 - 非同期プログラミングのための

+0

は何の問題あなたが解決しようとしている:?初めてコールgetダイレクトを必要とする - とのために、このすべてを開始しましたかリモートホストから1つのデータムをフェッチするのに時間がかかる場合は、それを速くするために何もできません。問題は、データが返されるのを待っている間、あなたのプログラムが(おそらく他のスレッドで)何をすることができるかということです。 –

+0

@jameslarge、私はちょうど 'post'リクエストを送り、' get'関数で 'InternetReadFile'を介して共振(数バイト)を読みます。それはsooo(私の場合は1秒)をしてはいけません。 –

+0

それほど遅くはありませんが、相手側のサーバーとその間のルータを制御しないと、何もないかもしれませんそれをスピードアップすることができます。あなたはあなたの質問に '[multithreading]'タグと '' [asynchronous] 'タグを入れます。どうして?クライアントプログラムでマルチスレッドまたは非同期IOを使用してサーバーを高速化することはできませんが、どちらか一方を使用してサーバーが応答するのを待つ間にクライアントが他の処理を実行できるようにすることはできません。あなたのクライアントが待っている間に他には何ができるのですか? –

答えて

0

おかげで、あなたは状態を維持するだろういくつかのオブジェクトを作成する必要があります。通常のファイル(ソケット)ハンドルなど

ファンクションsome_func()は別のパターンを持つ必要があります。オブジェクトのメンバ関数でなければなりません。ループ内で非同期のgetを呼び出すことはできません。 getに電話をかけた後、ただ終了する必要があります。 getによって開始される非同期操作が完了すると、コールバックが呼び出される必要があります(失敗した場合は、非同期操作を開始するために、このコールバックをエラーコードとともに呼び出す必要があります)。コールバックでは、オブジェクトへのポインタを持ち、それを使用します - some_func()を呼び出します。従ってsome_func()は、前のgetの呼び出しの結果を開始する必要があります。エラーがない場合はエラーを確認し、受信したデータを処理します。オブジェクトの状態(あなたの場合はiq)を調整し、必要に応じてgetに再度電話してください。

begin -> get() -> .. callback .. -> some_func() -> exit 
     ^       ┬ 
      └─────────────────────────────┘ 

(非同期読み取りファイル付き)、いくつかのデモ例

struct SOME_OBJECT 
{ 
    LARGE_INTEGER _ByteOffset; 
    HANDLE _hFile; 
    LONG _dwRef; 
    int _i, _q; 

    SOME_OBJECT() 
    { 
     _i = 0, _q = 0; 
     _dwRef = 1; 
     _ByteOffset.QuadPart = 0; 
     _hFile = 0; 
    } 

    void beginGet(); 

    void DoSomething(PVOID pvData, DWORD_PTR cbData) 
    { 
     DbgPrint("DoSomething<%u,%u>(%x, %p)\n", _i, _q, cbData, pvData); 
    } 

    // some_func 
    void OnComplete(DWORD dwErrorCode, PVOID pvData, DWORD_PTR cbData) 
    { 
     if (dwErrorCode == NOERROR) 
     { 
      DoSomething(pvData, cbData); 

      if (++_q == 5) 
      { 
       _q = 0; 

       if (++_i == 10) 
       { 
        return ; 
       } 
      } 

      _ByteOffset.QuadPart += cbData; 

      beginGet(); 
     } 
     else 
     { 
      DbgPrint("OnComplete - error=%u\n", dwErrorCode); 
     } 
    } 

    ~SOME_OBJECT() 
    { 
     if (_hFile) CloseHandle(_hFile); 
    } 

    void AddRef() { InterlockedIncrement(&_dwRef); } 

    void Release() { if (!InterlockedDecrement(&_dwRef)) delete this; } 

    ULONG Create(PCWSTR FileName); 
}; 

struct OPERATION_CTX : OVERLAPPED 
{ 
    SOME_OBJECT* _pObj; 
    BYTE _buf[]; 

    OPERATION_CTX(SOME_OBJECT* pObj) : _pObj(pObj) 
    { 
     pObj->AddRef(); 
     hEvent = 0; 
    } 

    ~OPERATION_CTX() 
    { 
     _pObj->Release(); 
    } 

    VOID CALLBACK CompletionRoutine(DWORD dwErrorCode, DWORD_PTR dwNumberOfBytesTransfered) 
    { 
     _pObj->OnComplete(dwErrorCode, _buf, dwNumberOfBytesTransfered); 

     delete this; 
    } 

    static VOID CALLBACK _CompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, OVERLAPPED* lpOverlapped) 
    { 
     static_cast<OPERATION_CTX*>(lpOverlapped)->CompletionRoutine(RtlNtStatusToDosError(dwErrorCode), dwNumberOfBytesTransfered); 
    } 

    void CheckResult(BOOL fOk) 
    { 
     if (!fOk) 
     { 
      ULONG dwErrorCode = GetLastError(); 

      if (dwErrorCode != ERROR_IO_PENDING) 
      { 
       CompletionRoutine(dwErrorCode, 0); 
      } 
     } 
    } 

    void* operator new(size_t cb, size_t ex) 
    { 
     return ::operator new(cb + ex); 
    } 

    void operator delete(PVOID pv) 
    { 
     ::operator delete(pv); 
    } 
}; 

ULONG SOME_OBJECT::Create(PCWSTR FileName) 
{ 
    HANDLE hFile = CreateFile(FileName, FILE_READ_DATA, FILE_SHARE_READ, 0, 
     OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); 

    if (hFile != INVALID_HANDLE_VALUE) 
    { 
     _hFile = hFile; 

     if (BindIoCompletionCallback(hFile, OPERATION_CTX::_CompletionRoutine, 0)) 
     { 
      return NOERROR; 
     } 
    } 

    return GetLastError(); 
} 

void SOME_OBJECT::beginGet() 
{ 
    const ULONG cbRead = 0x1000; 

    if (OPERATION_CTX* ctx = new(cbRead) OPERATION_CTX(this)) 
    { 
     ctx->Offset = _ByteOffset.LowPart; 
     ctx->OffsetHigh = _ByteOffset.HighPart; 
     ctx->CheckResult(ReadFile(_hFile, ctx->_buf, cbRead, 0, ctx)); 
    } 
} 

void ADemo(PCWSTR FileName) 
{ 
    if (SOME_OBJECT* pObj = new SOME_OBJECT) 
    { 
     if (!pObj->Create(FileName)) 
     { 
      pObj->beginGet(); 
     } 
     pObj->Release(); 
    } 
} 
関連する問題