#c_sharp
public interface IService { bool Process(Info info, SshTunnel ssh); } public class Service : IService { public bool Process(Info info, SshTunnel ssh) { var personalInfo = new GetPersonalInfo(ssh); if (personalInfo == null) return false; var totalPoints = GetTotalPoints(ssh); if (personalInfo == null) return false; return true; } private SomeInfo GetPersonalInfo(SshTunnel ssh) { //Example try { //Get personal info } catch(NetworkException ex) { } return new SomeInfo(); } private SomeInfo GetTotalPoints(SshTunnel ssh) { //Example try { //Get total points } catch (NetworkException ex) { // } return new SomeInfo(); } } Есть 2 варианта работы данного класса если в каком-то из методов GetTotalPoints или GetPersonalInfo упал ssh: Сразу же заменить его на новый и продолжить работу (С того метода, в котором он упал, что бы не запрашивать заново уже полученные данные. Например если ssh перестал работать в GetTotalPoints, а GetPersonalInfo успешно получил данные) Получить новый ssh и запрашивать данные через него с самого начала, даже если один из методов успешно получил данные. Проблема следующая.. В случае, когда мне нужно получить новый туннель и начать выполнение метода Process с самого начала, без сохранения прогресса, я просто возвращаю false, получаю новый туннель и запускаю данный метод заново. А вот как сделать второй случай, когда мне не нужно начинать выполнение заново, а именно с того места, в котором туннель упал, что бы не запрашивать уже полученные данные заново, я не понимаю как! Класс, который это всё запускает public class Processer { private IService service; private InfoSource infoSource; private SshList sshList; public Processer(IService _service) { service = _service; infoSource = Map.GetInfoSource(); sshList = Map.GetSSHList(); } public void Run() { // Случай, когда нужно выполнить метод без сохранения прогресса (с начала) bool IsPassed; var info = infoSource.Take(); do { var ssh = sshList.Take(); IsPassed = service.Process(info, ssh); } while (!IsPassed); } }
Ответы
Ответ 1
Вам нужно реализовать простенький конечный автомат. Ваш класс может выглядеть так, и вы сможете добавлять новые шаги, если понадобиться: public class Service : IService { private enum State { Begin, GetPersonalInfo, GetTotalPoints, End } private State _state = State.Begin; public bool Process(Info info, SshTunnel ssh) { while (true) { switch (_state) { case State.Begin: _state = State.GetPersonalInfo; break; case State.GetPersonalInfo: var personalInfo = GetPersonalInfo(ssh); if (personalInfo == null) return false; else _state = State.GetTotalPoints; break; case State.GetTotalPoints: var totalPoints = GetTotalPoints(ssh); if (totalPoints == null) return false; else _state = State.End; break; case State.End: return true; } } } // ... } Так как компилятор сам умеет строить такие автоматы (для асинхронных методов, или для методов использующих yield), то можно поручить эту работу ему. Пример: public interface IService { } public class Info { } public class SshTunnel { } public class Service : IService { private SshTunnel _ssh; private IEnumerator_proccessStateMachine; public bool Process(Info info, SshTunnel ssh) { _ssh = ssh; if (_proccessStateMachine == null) // извлекаем IEnumerator _proccessStateMachine = ProcessInternal().GetEnumerator(); _proccessStateMachine.MoveNext(); return _proccessStateMachine.Current; } private IEnumerable ProcessInternal() { // код выглядит как обычный, только с yield while (true) { var personalInfo = GetPersonalInfo(_ssh); if (personalInfo == null) yield return false; else break; } while (true) { var totalPoints = GetTotalPoints(_ssh); if (totalPoints == null) yield return false; else break; } yield return true; } // эмуляция нестабильной работы private int counter; private object GetPersonalInfo(SshTunnel ssh) { Console.WriteLine("GetPersonalInfo"); Thread.Sleep(300); if (++counter % 5 == 0) return new object(); return null; } private object GetTotalPoints(SshTunnel ssh) { Console.WriteLine("GetTotalPoints"); Thread.Sleep(300); if (++counter % 5 == 0) return new object(); return null; } } static class Program { static void Main(string[] args) { var service = new Service(); while (!service.Process(null, null)) ; } }
Комментариев нет:
Отправить комментарий