Я собираюсь сделать все возможное на английском, чтобы объяснить проблему. В настоящее время я пытаюсь Xamarin проверить, перенесем ли мы приложение IOS и приложение для Android на это, потому что это кажется действительно приятным.Xamarin IOS не может создать задачу async contoller
Небольшой тест, который я делаю, просто проверяет мою простую страницу входа.
Я действительно новичок в CSharp, так что извините заранее, если я задам глупые и простые вопросы ...
Я познакомлю первую реализацию, то проблема в то конце этого поста.
[РЕАЛИЗАЦИЯ]
Так это то, что я сделал с помощью RestSharp (Rest library client) библиотеки из самородков. У меня есть общий проект, который будет использоваться в приложении Android App и IOs (чтобы сделать работу только один раз). Я работаю с Xamarin Studio на Mac.
В моем LoginApiManager.cs у меня есть «основная» реализация, как это:
public interface UserConnectionStates
{
//Regroup all state created above
void userIsConnected(User user);
void userConnectionFailed(IRestResponse<User> response);
void userDisconnected();
}
public class LoginApiManager : RestManager
{
//Used for instance and shared element
public static LoginApiManager instance;
//Permits to store the information about the current loged in user
private User loggedInUser;
//All listeners for that class
private List<UserConnectionStates> userConnectionStatesListeners = new List<UserConnectionStates>();
public LoginApiManager()
{
//Create the the Rest Client to make Api Calls
base.client = new RestClient();
client.BaseUrl = new Uri(apiPath);
client.Authenticator = new HttpBasicAuthenticator(null, null);
}
public static LoginApiManager getInstance()
{
if (instance != null)
{
return instance;
}
else
{
return new LoginApiManager();
}
}
//------- UserConnectionStates Listeners accessors --------
public void addUserConnectionStatesListener(UserConnectionStates listener)
{
if (!userConnectionStatesListeners.Contains(listener))
{
userConnectionStatesListeners.Add(listener);
}
}
public void removeUserConnectionStatesListener(UserConnectionStates listener)
{
if (userConnectionStatesListeners.Contains(listener))
{
userConnectionStatesListeners.Remove(listener);
}
}
/*
* Permits to connect a user with a given username and password. It will
* call the API and return a User Object containing all information needed
* for connection, including token.
*/
public void connectUserWithUserNameAndPassword(string username, string password)
{
var request = new RestRequest(Method.POST);
request.Resource = "/myApiEndpoints/";
//Add it to the request
request.AddParameter("username", username);
request.AddParameter("password", password);
//Execute the query
client.ExecuteAsync<User>(request, (response) =>
{
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
//We serialize the user from response
loggedInUser = response.Data;
foreach (var l in this.userConnectionStatesListeners)
{
l.userIsConnected(response.Data);
}
}
else
{
//We send error to the code
foreach(var l in this.userConnectionStatesListeners)
{
l.userConnectionFailed(response);
}
}
});
}
}
... Хорошо, давайте продолжать, мой LoginViewController реализации UserConnectionStates интерфейса и ссылки на себя в список слушателей, чтобы получать информацию о различных изменениях состояний соединения. Так же, как это:
в моем LoginController.cs
public partial class LoginController : UIViewController, UserConnectionStates
{
//Some code here ...
public override void ViewDidLoad()
{
base.ViewDidLoad();
loginManager = LoginApiManager.getInstance();
loginManager.addUserConnectionStatesListener(this); //we create a listener for information about user connection
}
//Here comme the interface methods...
//Interface for listening user connection state
public void userIsConnected(User user)
{
var alertController = UIAlertController.Create("Connexion", "Connexion Success!",UIAlertControllerStyle.Alert);
alertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null));
this.PresentViewController(alertController, true, null);
}
public void userConnectionFailed(IRestResponse<User> response)
{
var alert= UIAlertController.Create("Connexion", "Unable to connect", UIAlertControllerStyle.Alert);
alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null));
PresentViewController(alert, animated: true, completionHandler: null);
}
public void userDisconnected()
{
}
}
[ПРОБЛЕМА]
... Вот моя проблема, когда client.ExecuteAsync (запрос (ответ)) вызывается в качестве примера для успеха, он вызовет метод интерфейса, реализованный объектом-слушателем public void userIsConnected (Пользователь пользователя) моего LoginController, но поскольку он вызывается в другом потоке, он останавливается на
var alertController = UIAlertController.Create("Connexion", "Connexion Success!",UIAlertControllerStyle.Alert);
nos crashes просто останавливаются и ничего не делают.
Я сделал тест с помощью простого
IRestResponse response = client.Execute(request);
и это работает, потому что метод является синхронным и вызывается в том же потоке, но он блокирует пользовательский интерфейс, пока задача не будет сделана ...
Каким образом CSharp или Xamarin лучше всего реализовать такие шаблоны? Если есть другой способ сделать такие вещи, я узнаю об этом, но поскольку я новичок в этом, я не знаю, что является лучшей практикой для такого рода вещей, и я не нашел этого в документации (это конечно, но не жалею).
Заранее большое спасибо за вашу помощь,
С уважением, Kevin
Возможно, это поможет вам: https://msdn.microsoft.com/en-us/magazine/dn605875.aspx?f=255&MSPPError=-2147217396 –
Спасибо, я собираюсь посмотреть! – kevzzz