2013-06-26 2 views
2

Это то, что я нашел в Windows 7. Приложение sid для прилива в окнах создает новый экземпляр, если дважды щелкнуть по ярлыку, даже если предыдущий экземпляр уже существует. Вы можете наблюдать то же самое на Tide SDK Developer (1.4.2), просто запустите приложение, и если вы снова нажмете на ярлык, он запустит новый экземпляр вместо того, чтобы просто показывать уже существующий. Кто-нибудь знает, как это исправить? Или кто-нибудь это исправил?Несколько экземпляров в Windows

OSX версии не отображает такие проблемы, хотя

ответ

0

Так я нашел способ решения этого в окнах. Создать процесс с помощью Ti.Process и дайте ему запускать следующую команду

tasklist | find "YourAppName" 

Если экземпляр уже существует, то он возвращает эту строку, если нет, то возвращает пустую строку. Вы можете проверить это каждый раз, когда вы запускаете приложение, чтобы избежать нескольких экземпляров.

0

Запуск tasklist в фоновом режиме зависит от платформы, и это решение предотвращает запуск нового экземпляра - это не будет фокусировать уже запущенный экземпляр. Существует еще одно решение, которое использует метод Ti.FileSystem.File.touch(): этот метод попытается создать указанный файл и вернет true, если он преуспел, или false, если файл уже существует. Самое главное, это атомный, то есть он не должен вводить условие гонки для вашего приложения.

Чтобы сфокусировать уже запущенный экземпляр, вы должны сообщить ему, что он должен (показывать и) фокусировать себя. Рабочий подход состоял бы в том, чтобы запустить HTTP-сервер, как только приложение узнает, что это единственный экземпляр, и сосредоточиться, когда он получает запрос. Если приложение обнаруживает при запуске, что другой экземпляр уже запущен, вместо этого создайте HTTP-клиент, подключитесь к HTTP-серверу другого экземпляра и отправьте ему запрос; когда запрос будет завершен, выйдите.

Пример реализации (чтобы поставить в начало файла app.js):

// enclose the logic in a closure, just to play it safe 
(function(pidFile) { 

    // if creating the PID file fails, i.e. there is another instance 
    // of the app already running 
    if (!pidFile.touch()) { 

     // create a HTTP client 
     var client = Ti.Network.createHTTPClient({}); 

     // add some event handlers 
     client.onload = function() { 
      Ti.App.exit(); 

     }; 

     client.onerror = function() { 
      Ti.App.exit(); 

     }; 

     // and dispatch 
     client.open('GET', 'http://localhost:9731/'); 
     client.send(); 

    } else { 
     // or, if creating the PID file succeeds, 
     // create a HTTP server and listen for incoming requests 
     var server = Ti.Network.createHTTPServer(); 

     server.bind(9731, 'localhost', function(request, response) { 
      // this handler gets run when another instance of the app 
      // is launched; that's where you want to show the app window 
      // if it is hidden and focus it 

      if (!Ti.UI.getMainWindow().isVisible()) { 
       Ti.UI.getMainWindow().show(); 

      } 

      Ti.UI.getMainWindow().focus(); 

      // send some response back to the other instance 
      response.setContentType('text/plain'); 
      response.setContentLength(2); 
      response.setStatusAndReason('200', 'OK'); 
      response.write('OK'); 

     }); 

     // an important thing is to clean up on application exit 
     // - you want to remove the PID file once the application 
     // exits, or you wouldn't be able to run it again until you 
     // deleted the file manually, something you don't want the end user 
     // to deal with 
     Ti.API.addEventListener(Ti.EXIT, function() { 
      server.close(); 
      pidFile.deleteFile(); 

     }); 

    } 

// now call the closure passing in an instance of the Ti.Filesystem.File class 
// wrapping the PID file in you app data directory 
})(Ti.Filesystem.getFile(Ti.API.Application.getDataPath(), 'run.pid')); 

Там может быть более легкий способ соединить два экземпляра через Ti.Network.TCPSocket класса (я глядя в это я прямо сейчас). Еще одна вещь, о которой нужно помнить, - это то, что приложение может потерпеть крах, не получив очистки после себя и, таким образом, впоследствии не получив вообще никакого эффекта. Таким образом, в обработчике событий onerror HTTPClient более разумный подход, чем отказ, состоял в том, чтобы представить пользователю диалог в соответствии с «Приложение уже запущено и не отвечает, или оно недавно потерпело крах. заставить запустить приложение? " Кроме того, порт сервера может быть уже использован другим приложением или, возможно, зомби из разбитого предыдущего запуска вашего приложения. Приведенный код не учитывает это (просто sayin ').