powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Асинхронный вызов хранимки
17 сообщений из 17, страница 1 из 1
Асинхронный вызов хранимки
    #39335122
Kolu4ka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет.
Есть приложение которое делает некоторый расчет данных, данные помещает в очередь TaskQueue, затем запускается метод в отдельном потоке который асинхронно запускает хранимку в MS SQL 2008R2. Поскольку очередь вырастает до тысяч, то решено параллельно держать например 10(Maxtasks) вызовов. Но по факту в мониторе активности число соединений гораздо больше, что приводит к ошибке -"слишком много соединений на сессию" и потери соединения. Что не так?
Код: 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.
private void DoTasks()
        {
            SqlCommand command;
            AsyncCallback callback;
            this.Errors = new List<string>();

            using (SqlConnection conn = new SqlConnection("Server=192.168.1.100; Database=test; User Id=test; Password=test; MultipleActiveResultSets=true; Asynchronous Processing=true"))
            {
                conn.Open();
                while (this.IsProgress)
                {                    
                    while (this.TaskQueue.Count != 0)
                    {
                        if (this.tasks < this.Maxtasks)
                        {
                            this.tasks++;
                            try
                            {
                                command = new SqlCommand("exec test "+this.TaskQueue.Dequeue().ToString() , conn);
                                callback = new AsyncCallback(HandleCallback);
                                command.BeginExecuteNonQuery(callback, command);
                            }
                            catch (Exception e)
                            {
                                this.Errors.Add(e.Message);
                                this.tasks--;
                            }
                        }
                    }
                }
            }
        }

        private void HandleCallback(IAsyncResult result)
        {
            this.tasks--;
        }
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335233
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kolu4ka,
Дергай EndExecuteNonQuery в HandleCallback.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335412
Kolu4ka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЕвгенийВ, спасибо!
Дернула
(result.AsyncState as SqlCommand).EndExecuteNonQuery(result);
в HandleCallback'е и все заработало.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335429
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
async\await не позволяет религия использовать или какие то требования?
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335455
Kolu4ka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Roman Mejtes, Visual Studio 2010
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335465
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesasync\await не позволяет религия использовать или какие то требования?
Обсуждали уже - в ряде случаев (а у ТС как раз такой случай - очередь с тысячами экземпляров и параллельными вызовами) BeginXXX/EndXXX будет эффективнее async/await.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335859
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныRoman Mejtesasync\await не позволяет религия использовать или какие то требования?
Обсуждали уже - в ряде случаев (а у ТС как раз такой случай - очередь с тысячами экземпляров и параллельными вызовами) BeginXXX/EndXXX будет эффективнее async/await.Так ведь ничто не мешает использовать Task.FromAsync для преобразования BeginXXX/EndXXX в Task, чтобы при этом использовались I/O ports.

Ну и если VS2010, то ничто не мешает использовать Task.ContinueWith вместо await.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335861
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КТак ведь ничто не мешает использовать Task.FromAsync для преобразования BeginXXX/EndXXX в Task, чтобы при этом использовались I/O ports.
Я опять же, как в теме по ссылке выше, предполагаю, что речь идет об использовании async/await вместо BeginXXX/EndXXX, но не совместно.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335874
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныАлексей КТак ведь ничто не мешает использовать Task.FromAsync для преобразования BeginXXX/EndXXX в Task, чтобы при этом использовались I/O ports.
Я опять же, как в теме по ссылке выше, предполагаю, что речь идет об использовании async/await вместо BeginXXX/EndXXX, но не совместно.
async/await все равно дернут внутри BeginXXX/EndXXX. Код станет толще и все, хотя удобнее вызов.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335898
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВСон Веры Павловныпропущено...

Я опять же, как в теме по ссылке выше, предполагаю, что речь идет об использовании async/await вместо BeginXXX/EndXXX, но не совместно.
async/await все равно дернут внутри BeginXXX/EndXXX.Смотря как напишешь.
ЕвгенийВКод станет толще и все, хотя удобнее вызов.Бывают случаи, когда удобство становится необходимостью.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39335967
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КСмотря как напишешь.
Вот дизасемблировал.
Код: 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.
// System.Data.SqlClient.SqlCommand
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
{
	SqlCommand.<>c__DisplayClass166_0 <>c__DisplayClass166_ = new SqlCommand.<>c__DisplayClass166_0();
	Bid.CorrelationTrace("<sc.SqlCommand.ExecuteNonQueryAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", this.ObjectID);
	SqlConnection.ExecutePermission.Demand();
	<>c__DisplayClass166_.source = new TaskCompletionSource<int>();
	<>c__DisplayClass166_.registration = default(CancellationTokenRegistration);
	if (cancellationToken.CanBeCanceled)
	{
		if (cancellationToken.IsCancellationRequested)
		{
			<>c__DisplayClass166_.source.SetCanceled();
			return <>c__DisplayClass166_.source.Task;
		}
		<>c__DisplayClass166_.registration = cancellationToken.Register(new Action(base.CancelIgnoreFailure));
	}
	Task<int> task = <>c__DisplayClass166_.source.Task;
	try
	{
		this.RegisterForConnectionCloseNotification<int>(ref task);
		Task<int>.Factory.FromAsync(new Func<AsyncCallback, object, IAsyncResult>(this.BeginExecuteNonQueryAsync), new Func<IAsyncResult, int>(this.EndExecuteNonQueryAsync), null).ContinueWith(new Action<Task<int>>(<>c__DisplayClass166_.<ExecuteNonQueryAsync>b__0), TaskScheduler.Default);
	}
	catch (Exception exception)
	{
		<>c__DisplayClass166_.source.SetException(exception);
	}
	return task;
}


Алексей КБывают случаи, когда удобство становится необходимостью.
Да кто же спорит :) Пусть работает компьютер, а я схожу покурю.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39336004
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВАлексей КСмотря как напишешь.
Вот дизасемблировал.
Код: 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.
// System.Data.SqlClient.SqlCommand
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
{
	SqlCommand.<>c__DisplayClass166_0 <>c__DisplayClass166_ = new SqlCommand.<>c__DisplayClass166_0();
	Bid.CorrelationTrace("<sc.SqlCommand.ExecuteNonQueryAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", this.ObjectID);
	SqlConnection.ExecutePermission.Demand();
	<>c__DisplayClass166_.source = new TaskCompletionSource<int>();
	<>c__DisplayClass166_.registration = default(CancellationTokenRegistration);
	if (cancellationToken.CanBeCanceled)
	{
		if (cancellationToken.IsCancellationRequested)
		{
			<>c__DisplayClass166_.source.SetCanceled();
			return <>c__DisplayClass166_.source.Task;
		}
		<>c__DisplayClass166_.registration = cancellationToken.Register(new Action(base.CancelIgnoreFailure));
	}
	Task<int> task = <>c__DisplayClass166_.source.Task;
	try
	{
		this.RegisterForConnectionCloseNotification<int>(ref task);
		Task<int>.Factory.FromAsync(new Func<AsyncCallback, object, IAsyncResult>(this.BeginExecuteNonQueryAsync), new Func<IAsyncResult, int>(this.EndExecuteNonQueryAsync), null).ContinueWith(new Action<Task<int>>(<>c__DisplayClass166_.<ExecuteNonQueryAsync>b__0), TaskScheduler.Default);
	}
	catch (Exception exception)
	{
		<>c__DisplayClass166_.source.SetException(exception);
	}
	return task;
}

Там, конечно же, всё правильно. Но можно же написать и неправильно:
Код: c#
1.
2.
3.
4.
public Task<int> ExecuteNonQueryAsync()
{
    return Task.Run(() => ExecuteNonQuery());
}
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39336059
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КТам, конечно же, всё правильно. Но можно же написать и неправильно:
Код: c#
1.
2.
3.
4.
public Task<int> ExecuteNonQueryAsync()
{
    return Task.Run(() => ExecuteNonQuery());
}


Так то оно так, только не научай человеков нехорошему :)
Поток отдельный запустишь, может спасешь гуй от повисания, но тот поток все равно будет ждать и бездействовать.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39336073
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВАлексей КТам, конечно же, всё правильно. Но можно же написать и неправильно:
Код: c#
1.
2.
3.
4.
public Task<int> ExecuteNonQueryAsync()
{
    return Task.Run(() => ExecuteNonQuery());
}


Так то оно так, только не научай человеков нехорошему :)
Поток отдельный запустишь, может спасешь гуй от повисания, но тот поток все равно будет ждать и бездействовать.Так для того и приведён пример, чтобы показать, как не надо делать. :-)
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39336089
super-code
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Алексей К, а надо как написать, чтобы было правильно?
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39336122
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
super-codeАлексей К, а надо как написать, чтобы было правильно?Примерно так, как привёл пример ЕвгенийВ, с использованием Task.Factory.FromAsync.
...
Рейтинг: 0 / 0
Асинхронный вызов хранимки
    #39336131
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
super-codeАлексей К, а надо как написать, чтобы было правильно?С другой стороны, правильно - это что-то из области философии. В нашем случае различия в том, что или висит поток в ожидании I/O, или используется I/O port. Если висящий поток не является тонким местом, то оба способа являются правильными. :-)
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Асинхронный вызов хранимки
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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