powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / BeginExecuteReader и CommandTimeout. Как правильно ?
8 сообщений из 8, страница 1 из 1
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014354
Greenhorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Задача:
В главном потоке необходимо асинхронно выполнять поток команд к SQL_ю.
Результат выполнения в главном потоке не нужен.
Вся обработка результатов команд (успешных и нет) находится в CallBack_е.
Поэтому очень важно контролировать максимальное время выполнения каждой команды.

Проблема : "Свойство CommandTimeout игнорируется во время вызовов асинхронного метода, такого как BeginExecuteReader."

жопное решение
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlTypes;

namespace Test_Async
{
  class Program
  {
    static void ProcessAsyncMS(IAsyncResult result)
    {
      SqlCommand cmd = null;
      try
      {
        cmd = (SqlCommand)result.AsyncState;
        SqlDataReader reader = cmd.EndExecuteReader(result);

        if (reader != null)
        {
          while (reader.Read())
            Console.WriteLine("Read RS");
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("Err:" + ex.Message);
      }
      finally 
      {
        if (cmd != null)
        {
          SqlConnection con = cmd.Connection;
          if (con != null)
            con.Close();
        }
      }
    }

    private static void TimerCallback(Object obj)
    {
      IAsyncResult result = (IAsyncResult)obj;

      if (!result.IsCompleted)
      { 
        SqlCommand cmd = (SqlCommand)result.AsyncState;
        cmd.Cancel();
      }
    }

    static void Main(string[] args)
    {
      SqlConnection con = new SqlConnection("Persist Security Info=False;Integrated Security=true;server=(local)");
      
      con.Open();

      SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:10:03'; SELECT 1/0 as [QQQ]", con);
      cmd.CommandTimeout = 1;

      AsyncCallback CB = new AsyncCallback(ProcessAsyncMS);

      IAsyncResult result = cmd.BeginExecuteReader(CB, cmd);
      Timer t = new Timer(
            TimerCallback
          , result
          , 1000
          , Timeout.Infinite
        );

      Console.ReadLine();
    }
  }
}



А как правильно решить такую задачу ?
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014428
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GreenhornА как правильно решить такую задачу ?задать таймаут на сервере?
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014476
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GreenhornА как правильно решить такую задачу ?
Сделать синхронное выполнение запроса в асинхронном таске c заданным таймаутом.
Antonariyзадать таймаут на сервере?
У запросов (не транзакций) этот таймаут server-scoped.
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014510
Greenhorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры ПавловныGreenhornА как правильно решить такую задачу ?
Сделать синхронное выполнение запроса в асинхронном таске c заданным таймаутом.
Antonariyзадать таймаут на сервере?
У запросов (не транзакций) этот таймаут server-scoped.

В асинхронном таске, конечно, можно.
Одна беда - при синхронном выполнении запроса (в другом потоке) точно потеряем поток.
А в случае асинхронного выполнения есть шанс, что поток останется в пуле потоков и будет востребован только тогда, когда запрос реально выполнится.
Именно по этому я и выбрал CallBack_и ...

Antonariy, какой таймаут на сервере ? "Remote Query TimeOut" ?
Ну во первых - каждый запрос имеет разное значение MaxCommandTimeOut (от 5 сек. до 5 мин.)
Во вторых это повлияет на всех, а не только на мою "маленькую" задачку.

Еще идеи ?
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014522
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GreenhornОдна беда - при синхронном выполнении запроса (в другом потоке) точно потеряем поток.
А в случае асинхронного выполнения есть шанс, что поток останется в пуле потоков и будет востребован только тогда, когда запрос реально выполнится.
С какого перепугу? Task 'и из TPL работают именно с пулом потоков:
For example, beginning with the .NET Framework 4 you can create Task and Task<TResult> objects, which perform asynchronous tasks on thread pool threads.
https://msdn.microsoft.com/en-us/library/0ka9477y(v=vs.110).aspx
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014561
Greenhorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры ПавловныGreenhornОдна беда - при синхронном выполнении запроса (в другом потоке) точно потеряем поток.
А в случае асинхронного выполнения есть шанс, что поток останется в пуле потоков и будет востребован только тогда, когда запрос реально выполнится.
С какого перепугу? Task 'и из TPL работают именно с пулом потоков:
For example, beginning with the .NET Framework 4 you can create Task and Task<TResult> objects, which perform asynchronous tasks on thread pool threads.
https://msdn.microsoft.com/en-us/library/0ka9477y(v=vs.110).aspx
С такого перепуга, что SqlCommand.ExecuteReader() в отдельном таске и в отдельном потоке из пула потоков будет использовать этот поток, пока не отработает -> Я так думаю !
Если Вы имеете информацию об обратном - огромная просьба - поделитесь ...
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014692
Greenhorn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры Павловны,

А вот и подтверждение того, что я прав:
Новый пример
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlTypes;

namespace Test_Async
{
  class Program
  {
    private static bool isCompete;
    static void ProcessAsyncMS(IAsyncResult result)
    {
      SqlCommand cmd = null;
      try
      {
        cmd = (SqlCommand)result.AsyncState;
        SqlDataReader reader = cmd.EndExecuteReader(result);

        if (reader != null)
        {
          while (reader.Read())
            Console.WriteLine("Read RS");
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("Err:" + ex.Message);
      }
      finally 
      {
        if (cmd != null)
        {
          SqlConnection con = cmd.Connection;
          if (con != null)
            con.Close();
        }
      }
      isCompete = true;
    }

    private static void TimerCallback(Object obj)
    {
      IAsyncResult result = (IAsyncResult)obj;

      if (!result.IsCompleted)
      { 
        SqlCommand cmd = (SqlCommand)result.AsyncState;
        cmd.Cancel();
      }
    }

    static void DoTestCallBack()
    {
      SqlConnection con = new SqlConnection("Persist Security Info=False;Integrated Security=true;server=(local)");

      con.Open();

      SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:10:03'; SELECT 1/0 as [QQQ]", con);
      cmd.CommandTimeout = 1;

      AsyncCallback CB = new AsyncCallback(ProcessAsyncMS);

      IAsyncResult result = cmd.BeginExecuteReader(CB, cmd);
      Timer t = new Timer(
            TimerCallback
          , result
          , 1000
          , Timeout.Infinite
        );
    }

    static void DoTestTask()
    {
      Action<object> action = (object obj) =>
      {
        SqlConnection con = new SqlConnection("Persist Security Info=False;Integrated Security=true;server=(local)");

        con.Open();

        SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:03'; SELECT 1/0 as [QQQ]", con);
        cmd.CommandTimeout = 1;
        try
        {
          SqlDataReader reader = cmd.ExecuteReader();
          while (reader.Read())
            Console.WriteLine("Read RS");
        }
        catch (Exception ex)
        {
          Console.WriteLine("Err:" + ex.Message);
        }
        finally
        {
          con.Close();
        }
      };

      Task t = new Task(action, "alpha");
      t.Start();

      while (!t.Wait(500))
      {
        int workerThreads;
        int completionPortThreads;
        ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);

        Console.WriteLine(String.Format("workerThreads: {0} ; completionPortThreads: {1}", workerThreads, completionPortThreads));
      }
    }

    static void Main(string[] args)
    {
      DoTestCallBack();

      while (!isCompete)
      {
        int workerThreads;
        int completionPortThreads;
        ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);

        Console.WriteLine(String.Format("workerThreads: {0} ; completionPortThreads: {1}", workerThreads, completionPortThreads));
        Thread.Sleep(500);
      }

      Console.WriteLine("END DoTestCallBack()");

      DoTestTask();
      
      Console.WriteLine("ALL DONE");
      Console.ReadLine();
    }
  }
}



Выхлоп
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
workerThreads: 1023 ; completionPortThreads: 1000
workerThreads: 1023 ; completionPortThreads: 1000
workerThreads: 1023 ; completionPortThreads: 1000
Err:При выполнении текущей команды возникла серьезная ошибка.. При наличии результатов они должны быть аннулированы.
Операция отменена пользователем.
END DoTestCallBack()
workerThreads: 1022 ; completionPortThreads: 1000
workerThreads: 1022 ; completionPortThreads: 1000
Err:Истекло время ожидания (Timeout). Время ожидания истекло до завершения операции или сервер не отвечает.
ALL DONE


Хотя при таком кол-ве потоков, может я на воду дую ?
...
Рейтинг: 0 / 0
BeginExecuteReader и CommandTimeout. Как правильно ?
    #39014878
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GreenhornА вот и подтверждение того, что я прав
А с чего вы взяли, что внутри
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
      while (!t.Wait(500))
      {
        int workerThreads;
        int completionPortThreads;
        ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);

        Console.WriteLine(String.Format("workerThreads: {0} ; completionPortThreads: {1}", workerThreads, completionPortThreads));
      }


по истечении таймаута таск уже должен отдать поток? таск еще жив, и держит этот поток. Вы вставьте вывод результата ThreadPool.GetAvailableThreads после того же ReadLine в конце теста, и посмотрите результат.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / BeginExecuteReader и CommandTimeout. Как правильно ?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]