none
Как правильно создать и использовать cancellation_token в приложении Win32 на C++? RRS feed

  • Вопрос

  • Здравствуйте. У меня проблемы с созданием токена отмены в приложении Win32. Создаю его следующим способом. В файле, где функции int APIENTRY wWinMain() и LRESULT CALLBACK WndProc вобщем в главном файле программы определяю:

    static cancellation_token_source cts; // источник токенов отмены

    Затем ниже, в оконной процедуре WndProc пишу:

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
         . . . . . .
    	switch (message)
    	{
    	    case WM_COMMAND:
    	    {
    		     . . . . . .
    			 case IDM_TRIANGULATE: // Нажатие на кнопку запуска триангуляции
    			 {
    			     // Получить токен отмены для задачи triangulationTask.
    				 cancellation_token token = cts.get_token();
    				 // Триангуляционная сетка
    				Mesh m;
    				// Настроечные параметры для приложения
    				Configuration b;
    				// Определить задачу для триангуляции.
    				auto triangulationTask = create_task([&m, &b, &token]()
    				{
    				    // Проверить, была ли отмена задачи.
    					if (token.is_canceled())
    					{
    						// Отменить триангуляцию.;
    						Concurrency::cancel_current_task();
    					}
    					else
    					{
    						// Запустить триангуляцию.
    			            DelaunayTriangulation delaunayTri;
    			            m.HullSize = delaunayTri.StartTriangulation(&m, &b, token);
    					}
    				}, token);
    			 }
    			 . . . . . .
    	    }
    	}
    	. . . . . .
    }

    При прогоне приложения в отладке постоянно попадаю в ветку

    if (token.is_canceled())
    т.е., получается что токен создаётся уже отменённым (каким-то образом устанавливается в состояние is cancelled при своём создании). Почему так? Скажите, пожалуйста. Может быть я что-то неправильно делаю? Буду очень благодарен за помощь.

    21 декабря 2019 г. 16:44

Ответы

  • Я исправил ситуацию, сделав по следующей схеме:

    static cancellation_token_source cancelTriSource;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            case WM_COMMAND:
    		{
    		    int wmId = LOWORD(wParam);
    			switch (wmId)
    			{
    			    case IDM_ABOUT:       // Вывести на экран окно с информацией о приложении.
    					DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    					break;
    					.
    					.
    					.
    				case IDM_TRIANGULATE:
    				{
    					auto asyncTask = create_task([]()
    					{ 
    						cancelTriSource = cancellation_token_source();
    						cancellation_token token = cancelTriSource.get_token();
    						auto triangulationTask = create_task([&token]()
    						{
    							// Здесь выполняется триангуляция,
    							// функции которой проверяют - был ли
    							// отменён токен.
    							// Если обнаружено, что токен отменён,
    							// то вызывается cancel_current_task();.
    						}, token);
    						
    						// Ожидать окончания задачи триангуляции.
    						triangulationTask.get();
    					});
    				}				
    				break;
    				    .
    					.
    					.
    				default:
    					return DefWindowProc(hWnd, message, wParam, lParam);	
    			}
    		}
    		break;
    		.
    		.
    		.
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);	
    	}
    }
    Сейчас использование токена отмены работает. Так что смотрите и пользуйтесь, пожалуйста. Только вот хотелось бы уточнить, правильно ли то, что я вставил обработку нажатий на кнопку тулбара в WM_COMMAND. Потому что IDM_TRIANGULATE - это у меня обработка щелчка по кнопке "Выполнить триангуляцию", которая находится на toolbar. А IDM_ABOUT - это обработка щелчка по пункту "О программе", который находится в главном меню приложения, и обработка IDM_ABOUT была прописана при создании приложения.


    • Изменено Purple_Apple 6 января 2020 г. 7:06
    • Помечено в качестве ответа Purple_Apple 6 января 2020 г. 7:06
    6 января 2020 г. 6:56

Все ответы

  • Я исправил ситуацию, сделав по следующей схеме:

    static cancellation_token_source cancelTriSource;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            case WM_COMMAND:
    		{
    		    int wmId = LOWORD(wParam);
    			switch (wmId)
    			{
    			    case IDM_ABOUT:       // Вывести на экран окно с информацией о приложении.
    					DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    					break;
    					.
    					.
    					.
    				case IDM_TRIANGULATE:
    				{
    					auto asyncTask = create_task([]()
    					{ 
    						cancelTriSource = cancellation_token_source();
    						cancellation_token token = cancelTriSource.get_token();
    						auto triangulationTask = create_task([&token]()
    						{
    							// Здесь выполняется триангуляция,
    							// функции которой проверяют - был ли
    							// отменён токен.
    							// Если обнаружено, что токен отменён,
    							// то вызывается cancel_current_task();.
    						}, token);
    						
    						// Ожидать окончания задачи триангуляции.
    						triangulationTask.get();
    					});
    				}				
    				break;
    				    .
    					.
    					.
    				default:
    					return DefWindowProc(hWnd, message, wParam, lParam);	
    			}
    		}
    		break;
    		.
    		.
    		.
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);	
    	}
    }
    Сейчас использование токена отмены работает. Так что смотрите и пользуйтесь, пожалуйста. Только вот хотелось бы уточнить, правильно ли то, что я вставил обработку нажатий на кнопку тулбара в WM_COMMAND. Потому что IDM_TRIANGULATE - это у меня обработка щелчка по кнопке "Выполнить триангуляцию", которая находится на toolbar. А IDM_ABOUT - это обработка щелчка по пункту "О программе", который находится в главном меню приложения, и обработка IDM_ABOUT была прописана при создании приложения.


    • Изменено Purple_Apple 6 января 2020 г. 7:06
    • Помечено в качестве ответа Purple_Apple 6 января 2020 г. 7:06
    6 января 2020 г. 6:56
  • Спасибо, что отписались с решением!

    Если Вам помог чей-либо ответ, пожалуйста, не забывайте жать на кнопку "Предложить как ответ" или "Проголосовать за полезное сообщение" Мнения, высказанные здесь, являются отражение моих личных взглядов, а не позиции корпорации Microsoft. Вся информация предоставляется "как есть" без каких-либо гарантий.

    6 января 2020 г. 8:06
    Модератор