2017-12-07 18 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 기능이 있습니까?

두 번째 질문은

어떻게 WinInet 그것을 실현하기 위해? 빨간색 MSDN을 가지고 있지만, 나에게 너무 힘들어. 더 새로운 것이 어쩌면 너는 더 단순하게 설명 할 수 있을까? 없는 지역 기능의 변수 만 개체의 멤버, 반대하는 필수 참조 카운트해야 현재의 경우 iq에서 - 비동기 프로그래밍을위한

+0

어떤 문제 것은 당신이 해결하기 위해 노력하고있다 : - 시작과 모든이 get 직접 처음으로 전화를해야합니까? 원격 호스트에서 하나의 데이터를 가져 오는 데 오랜 시간이 걸리는 경우 더 빠르게 수행 할 수있는 방법이 없습니다. 질문은 반환 할 데이터를 기다리는 동안 프로그램이 (다른 스레드에서) 무엇을 할 수 있는지 알려주는 것입니다. –

+0

@jameslarge, 나는 단지'post' 요청을 보내고'get' 함수에서'InternetReadFile'을 통해 공진 (몇 바이트)을 읽습니다. 그것은 sooo (abount 1 초 내 경우) 느린 –

+0

어쩌면 너무 느려져서는 안됩니다,하지만 당신이 다른 끝에서 라우터와 그 사이에 라우터를 제어하지 않으면 아무 것도 없을 수 있습니다 그것을 가속화 할 수 있습니다. 'multithreading'태그와'[asynchronous]'태그를 질문에 놓는다. 왜?클라이언트 프로그램에서 멀티 스레딩이나 비동기 I/O를 사용하여 서버를 더 빠르게 만들 수는 없지만 둘 중 하나를 사용하여 서버가 응답하기를 기다리는 동안 클라이언트가 다른 일을 할 수있게 할 수 있습니다. 고객이 기다리는 동안 수행해야 할 다른 작업은 무엇입니까? –

답변

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(); 
    } 
}