Форум программистов, компьютерный форум, киберфорум
C#: Web, ASP.NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 22.09.2016
Сообщений: 7
1

WebService await\async перестал работать

22.09.2016, 20:02. Показов 3229. Ответов 11

Author24 — интернет-сервис помощи студентам
Добрый день!

Делал первое приложение на ASP.NET WebForms, и понял что у меня весь интерфейс обрабатывается в jquery, а вот работа с бд и запросы к апи нужно переделать на WebService. Решил не грешить WCF, а запустить через стары добрый asmx, тем более у меня то все го 5 методов там. И вот скопировал я одну из функций, и она перестала работать. И не могу понять почему, и удручает меня это все больше и больше....

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static string jsonString;
 
public async Task<string> GetAllBikeStops()
    {
        List<BikePoints> bikePoints_List;
        HttpClient client = new HttpClient();
        HttpResponseMessage httpmessage = await client.GetAsync("api_string"); //здесь строка апи, ничего не менялось, она работает.
        httpmessage.EnsureSuccessStatusCode();
        string response = await httpmessage.Content.ReadAsStringAsync();
        //geted string
        bikePoints_List = await System.Threading.Tasks.Task.Factory.StartNew(() =>
                            JsonConvert.DeserializeObject<List<BikePoints>>(response));
        //make small copy in memory for jquery
        jsonString = await System.Threading.Tasks.Task.Factory.StartNew(() =>
                                JsonConvert.SerializeObject(bikePoints_List, Formatting.None));//, Formatting.Indented));
        return jsonString;
}
и засетовал я совсем, и решил спросить как так то? Где моя вина?

Добавлено через 9 минут
Собственно в дебаге как и должно быть, после первого await на строке 7 меня выкидывает. По завершению времени, я вижу что завершается два потока. Но jsonString остается null.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.09.2016, 20:02
Ответы с готовыми решениями:

Поисковик по каталогам перестал корректно работать
Скрипт ищет в каталоге user/, и далее в подкаталогах, так он делал до 19.09.01 а 20.09.01 выдет...

Сайт перестал работать после размещения на сервере
на локалке всё работает отлично, а на серваке выдаёт ету шибку: Unable to cast object of type...

WebService перестал работать после размещения на хостинге
Здравствуйте. Впервые написала веб-сервис, возвращающий картинку по входному параметру. На...

Async/ await как правильно ввести данные в async метод (консоль)
Привет , кто то может помочь ?) проблема в тому что у меня есть async метод который запускается...

11
3466 / 2476 / 696
Регистрация: 02.08.2011
Сообщений: 6,720
22.09.2016, 20:29 2
Цитата Сообщение от lenin122 Посмотреть сообщение
после первого await на строке 7 меня выкидывает
Оберните в Try-Catch и в Сatche - точку останова - Видимо, это exception.
0
0 / 0 / 0
Регистрация: 22.09.2016
Сообщений: 7
22.09.2016, 20:30  [ТС] 3
изменил строку 7:
C#
1
HttpResponseMessage httpmessage = await client.GetAsync("api_string")[B].ConfigureAwait(continueOnCapturedContext: false);[/B]
Заработало, однако функций возвращает в браузере:
XML
1
<TaskOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://lenin122testapp.somee.com/"/>
а хотелось бы стринг увидеть... Я его jquery через ajax думал вытянуть

Добавлено через 35 секунд
Цитата Сообщение от IamRain Посмотреть сообщение
Оберните в Try-Catch и в Сatche - точку останова - Видимо, это exception.

Оборачивал, так и не попал в Catch.
0
3466 / 2476 / 696
Регистрация: 02.08.2011
Сообщений: 6,720
22.09.2016, 20:56 4
А зачем вам десериализация из json, а затем последующая сериализация в него?
Может проще сразу вернуть response ?
+ Замечание: зачем таски городить везде, это ведь довольно емкий объект.
Имхо, один раз получили строку, дальше уже можно синхронный код писать.

Добавлено через 2 минуты
Я бы писал так:
C#
1
2
3
4
5
6
7
8
public async Task<string> GetAllBikeStops()
    {
        HttpClient client = new HttpClient();
        HttpResponseMessage httpmessage = await client.GetAsync("api_string"); //здесь строка апи, ничего не менялось, она работает.
        httpmessage.EnsureSuccessStatusCode();
        string response = await httpmessage.Content.ReadAsStringAsync();
        return response;
     }
Добавлено через 2 минуты
И смотрел бы в отладке, что там вообще возвращается.
0
0 / 0 / 0
Регистрация: 22.09.2016
Сообщений: 7
22.09.2016, 21:09  [ТС] 5
Цитата Сообщение от IamRain Посмотреть сообщение
А зачем вам десериализация из json, а затем последующая сериализация в него?
Может проще сразу вернуть response ?
+ Замечание: зачем таски городить везде, это ведь довольно емкий объект.
Имхо, один раз получили строку, дальше уже можно синхронный код писать.

Добавлено через 2 минуты
Я бы писал так:
C#
1
2
3
4
5
6
7
8
public async Task<string> GetAllBikeStops()
    {
        HttpClient client = new HttpClient();
        HttpResponseMessage httpmessage = await client.GetAsync("api_string"); //здесь строка апи, ничего не менялось, она работает.
        httpmessage.EnsureSuccessStatusCode();
        string response = await httpmessage.Content.ReadAsStringAsync();
        return response;
     }
Добавлено через 2 минуты
И смотрел бы в отладке, что там вообще возвращается.
В отладке все так и осталось, после первого же await из дебага я вываливаюь, в ответе пустой TaskString.

десериализация сохраняет все в список. Сам стринг весит 1.8 мб. После серилизациии я обрубаю 2\3 лишник полей и ужимаю его почти до 0.7 метра.

На счет лишних тасков согласен, в принципе 1.8 мб при десерилизации это совсем не тот объем который нужно в await через Task пихать.
0
3466 / 2476 / 696
Регистрация: 02.08.2011
Сообщений: 6,720
22.09.2016, 21:25 6
Покажите, как отправляете get-запрос. Раз уж на сервере возвращается json, то клиент должен ожидать json.
То есть надо, чтобы была строка: dataType: "json".
Судя по формату ответа, это что-то похожее на soap, afaik.
0
0 / 0 / 0
Регистрация: 22.09.2016
Сообщений: 7
22.09.2016, 21:33  [ТС] 7
Цитата Сообщение от IamRain Посмотреть сообщение
Покажите, как отправляете get-запрос. Раз уж на сервере возвращается json, то клиент должен ожидать json.
То есть надо, чтобы была строка: dataType: "json".
Судя по формату ответа, это что-то похожее на soap, afaik.
Для дебага захожу localhost:23421/myservice.asmx

Вызываю в jQuery:
Javascript
1
2
3
4
5
6
7
8
$.ajax({
            type: 'GET',
            url: 'MainForm.aspx/GetAllBikeStops',
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function onSuccessJSONGet(response, status) {
                PaintMarkers($.parseJSON(response.d));
            }
Для примера не async с бд работает без проблем.

Вызов JS:
Javascript
1
2
3
4
5
6
7
8
9
10
$.ajax({
                type: 'POST',
                url: '/LondonBikePointFinderService.asmx/RefreshTopPoints',
                data: JSON.stringify({ topValue: topPointsToShow }),
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function onSuccessRefreshGet(response, status) {
                    $('#top_table_div').html(response.d);
                }
            });
И сама функция:
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
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    [WebMethod(Description = "Refreshing top viewed BikePoints in radius search")]
    public string RefreshTopPoints(int topValue)
    {
        using (var sqlConnection = new SqlConnection(WebConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString))
        {
            if (sqlConnection.State == System.Data.ConnectionState.Closed)
                sqlConnection.Open();
            var sqlCommand = new SqlCommand(@"
                                            SELECT TOP (@top_value)
                                                [commonName],[counter] 
                                            FROM
                                                [LONDONBASE].[dbo].[BIKEPOINTS]
                                            ORDER BY counter desc", sqlConnection);
            sqlCommand.Parameters.Add("@top_value", SqlDbType.SmallInt).Value = topValue.ToString();
            var resultSB = new StringBuilder();
 
            resultSB.Append(@"<table id='top_table'>");
            using (var sqlDataReader = sqlCommand.ExecuteReader())
            {
                while (sqlDataReader.Read())
                {
                    resultSB.Append(String.Format(@"<tr><td>{0}</td></tr>",
                        sqlDataReader.GetString(0), sqlDataReader.GetInt32(1).ToString()));
                }
            }
            
            resultSB.Append(@"</table>");
            return resultSB.ToString();
        }
 
    }
0
3466 / 2476 / 696
Регистрация: 02.08.2011
Сообщений: 6,720
22.09.2016, 21:43 8
Цитата Сообщение от lenin122 Посмотреть сообщение
не async с бд работает без проблем.
Отсюда нашел:
Using async with voids is not stable or reliable. However, all you have to do is call Page.RegisterAyncTask - it's not any trouble and you'll be in a better more flexible place.
Возможно, это распространяется и на методы, возвращающие ответ.
Попробуйте добавить:
C#
1
2
3
4
public void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(GetAllBikeStops));
}
0
0 / 0 / 0
Регистрация: 22.09.2016
Сообщений: 7
22.09.2016, 21:46  [ТС] 9
Цитата Сообщение от IamRain Посмотреть сообщение
Отсюда нашел:

Возможно, это распространяется и на методы, возвращающие ответ.
Попробуйте добавить:
C#
1
2
3
4
public void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(GetAllBikeStops));
}
А если страница просто html и GetAllBikeStops в WebMethod ?

Просто для понимания.

await у httpclient.getAsync работает так.
Поток где вызываем - сохраняет состояние.
Открывается новый поток, в котором выполняется сам getasync
далее по выполнению, мы должны передать результат в поток из которого вызывали.
После этого поток из которого вызывали продолжит работу.
0
3466 / 2476 / 696
Регистрация: 02.08.2011
Сообщений: 6,720
22.09.2016, 21:55 10
Попробуйте сначала так, в первоначальном посте ведь у вас именно так, как я понял.
Попробую у себя воспроизвести, отпишусь.
0
0 / 0 / 0
Регистрация: 22.09.2016
Сообщений: 7
22.09.2016, 22:23  [ТС] 11
Цитата Сообщение от IamRain Посмотреть сообщение
Попробуйте сначала так, в первоначальном посте ведь у вас именно так, как я понял.
Попробую у себя воспроизвести, отпишусь.
Уважаемы IamRain. Большое спасибо что убили на меня прекрасный вечер четверга, благо это не пятница.

После того, как я переносил свой код из Page в WebService, я сделал возвращаемый результат Task<string> и в ajax я должен был к ответу обращаться не как response.d а уже как response.d.Result

Все работает, из за того что я смотрел результат через обложку vмоего asmx, я видел только пустой xml, который действительно генерится после первого await.

Остался только вопрос, почему это работает если я не сохраняю Context.
Т.е. работает, только если в Ascyn операнд добавить .ConfigureAwait(continueOnCapturedContext: false):
C#
1
HttpResponseMessage httpmessage = await client.GetAsync("api_string").ConfigureAwait(continueOnCapturedContext: false);
0
3466 / 2476 / 696
Регистрация: 02.08.2011
Сообщений: 6,720
22.09.2016, 23:55 12
Цитата Сообщение от lenin122 Посмотреть сообщение
Остался только вопрос,
Вот тут я сам не в курсе, но, судя по ответу Stephen Cleary, фишка ConfigureAwait(false) в том, что когда мы await-им метод с использованием ConfigureAwait(false), мы берем из пула еще один поток, выполняем код метода, при этом по завершению работы метода переключения контекста происходить обратно не будет, и весь код, который выполняется после await, будет выполняться уже в контексте потока, который использовался для await операции, чего не происходит по-умолчанию.
Я понятия не имею, как отсутствие переключения контекста влияет на возврат результата async WebMethod-ами.
Буду рад, если кто объяснит.
Вот схожая проблема на so, но тут нет толкового объяснения, поэтому у меня нет к статье доверия.
0
22.09.2016, 23:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.09.2016, 23:55
Помогаю со студенческими работами здесь

async/await (._. )
Опять я с глупым вопросом. Не могу понять, почему метод, который выгружает данные не асинхронный?...

Async, await
Объясните работу async, await. Облазил весь интернет, но ничего толкового не нашел. Заранее...

Async/await
Мне нужно, чтобы пароль выводился по одному символу public Matrix() { ...

Async/await
В интернете копался ничего информативного не нашел, все в каких- то не понятных для новичка...

Async await
Пытыюсь разобраться с async/await но что то без успешно пока. Не подскажете как переделать этот код...

async/await
https://metanit.com/sharp/tutorial/13.7.php вот код Task&lt;T&gt;: // определение...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru