using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace SimpleMessageBus
{
/// <summary>
/// Рассылает события заинтересованным подписчикам
/// в рамках одного приложения.
/// </summary>
/// <remarks>Используются WeakReference, чтобы не было утечек памяти
/// на случай, если кто-то забудет отписаться. Поэтому не рекомендуется
/// использовать лямбда-обработчики событий.</remarks>
public static class MessageBus
{
private static readonly Dictionary<string, List<WeakReference<Action<string, object>>>> Subscribers =
new Dictionary<string, List<WeakReference<Action<string, object>>>>();
/// <summary>
/// Оформляет подписку на событие
/// </summary>
/// <param name="topic">Тип события</param>
/// <param name="handler">Подписчик</param>
public static void Subscribe(string topic,
Action<string, object> handler)
{
if (String.IsNullOrEmpty(topic))
throw new ArgumentNullException(nameof(topic));
if (handler == null)
throw new ArgumentNullException(nameof(handler));
List<WeakReference<Action<string, object>>> handlers;
lock (Subscribers)
if (!Subscribers.TryGetValue(topic, out handlers))
handlers = Subscribers[topic] = new List<WeakReference<Action<string, object>>>();
lock (handlers)
handlers.Add(new WeakReference<Action<string, object>>(handler));
}
/// <summary>
/// Отменяет подписку на событие
/// </summary>
/// <param name="topic">Тип события</param>
/// <param name="handler">Подписчик</param>
public static void Unsubscribe(string topic,
Action<string, object> handler)
{
if (String.IsNullOrEmpty(topic))
throw new ArgumentNullException(nameof(topic));
if (handler == null)
throw new ArgumentNullException(nameof(handler));
List<WeakReference<Action<string, object>>> list;
lock (Subscribers)
if (!Subscribers.TryGetValue(topic, out list))
return;
lock (list)
{
var i = 0;
while (i < list.Count)
{
var reference = list[i];
if (!reference.TryGetTarget(out var target))
list.RemoveAt(i); // Заодно очищаем список от мертвых подписчиков
else if (target == handler)
{
list.RemoveAt(i);
return;
}
}
}
}
/// <summary>
/// Оповещает подписчиков о наступлении события
/// </summary>
/// <param name="topic">Тип события</param>
/// <param name="data">Данные события</param>
public static void Publish(string topic, object data = null)
{
if (String.IsNullOrEmpty(topic))
throw new ArgumentNullException(nameof(topic));
List<WeakReference<Action<string, object>>> list;
lock (Subscribers)
if (!Subscribers.TryGetValue(topic, out list))
return;
var handlers = new List<Action<string, object>>();
lock (list)
{
var i = 0;
while (i < list.Count)
{
var reference = list[i];
if (!reference.TryGetTarget(out var target))
list.RemoveAt(i);
else
{
handlers.Add(target);
++i;
}
}
}
// В Unity вызывать обработчики событий, наверное,
// нужно как-то так:
UnityEngine.WSA.Application.InvokeOnAppThread(() =>
// А в обычном консольном приложении так:
// Task.Run(() =>
{
foreach (var handler in handlers)
{
try
{
handler.Invoke(topic, data);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}, false);
}
}
}
using System.Diagnostics;
using System.Threading.Tasks;
namespace SimpleMessageBus
{
public static class Program
{
public static async Task Main(string[] args)
{
Debug.WriteLine("Started.");
MessageBus.Subscribe("Rain", RainHandler);
MessageBus.Publish("Rain");
await Task.Delay(100); // Ждем, пока событие поступит
MessageBus.Unsubscribe("Rain", RainHandler);
Debug.WriteLine("Finished.");
}
private static void RainHandler(string topic, object data)
{
Debug.WriteLine("Event: " + topic);
}
}
}
UnityEngine.WSA.Application.InvokeOnAppThread()
— все-таки у нас целевая платформа Unity. document.addEventListener('click', function myClickHandler(evt) { // слушаем все клики
if (evt.target.matches('.selector')){ // проверяем был ли это клик по .selector
// do your stuff
}
});
document.addEventListener('click', function myClickHandler(evt) { // слушаем все клики
const elem = evt.target.closest('.selector');
if (elem){ // если клик мимо, то тут null
// do your stuff
}
});
function largestOfFour(matrix) {
let results = []; // переменная для хранения самых больших чисел из каждой строки матрицы
// итерация по матрице
for (let rowIndex = 0; i < matrix.length; i++) {
// переменнная, в которой будет храниться самое большое число из текущей строки матрицы
let largestNumber = matrix[rowIndex][0]; // первый элемент текущей строки в качестве значения по умолчанию
// итерация по строке матрицы
for (let rowElementIndex = 1; j < matrix[rowIndex].length; j++) {
// если текущий элемент больше самого большого числа на текущем этапе итерации_
if (arr[rowIndex][rowElementIndex] > largestNumber) {
// самым большим числом становится текущий элемент строки матрицы
largestNumber = arr[rowIndex][rowElementIndex];
}
}
// после итерации по строке матрицы сохраняет самое большое число
results[rowIndex] = largestNumber;
}
return results;
}
function largestOfFour(arr) {
return arr.map((row) => Math.max(...row))
}
style
, изображения сконвертировать в base64
и заменить в соответствующих атрибутах src
и значениях свойств background-*
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>example</title>
<style>
.bg-img{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
background-repeat: no-repeat;
padding-top: 10px;
}
</style>
</head>
<body>
<div>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
<p>Изображение красной точки в base64 (img src)</p>
</div>
<div class="bg-img">Изображение красной точки в base64 (background-image)</div>
</body>
</html>
public partial class BrowserMain : Form
{
public BrowserMain()
{
InitializeComponent();
WebBrowser = new ChromiumWebBrowser(
string.IsNullOrWhiteSpace(address) ? "about:blank" : address)
{
// ...
};
Controls.Add(WebBrowser);
WebBrowser.TitleChanged += WebBrowser_TitleChanged;
WebBrowser.AddressChanged += WebBrowser_AddressChanged;
WebBrowser.LoadingStateChanged += webBrowser_DocumentCompleted;
}
private void BrowserMain_FormClosing(object sender, FormClosingEventArgs e)
{
// После вызова этих строк методы WebBrowser_TitleChanged, WebBrowser_AddressChanged
// и webBrowser_DocumentCompleted не будут выполняться.
// Это и не нужно, так как окно закрывается.
WebBrowser.TitleChanged -= WebBrowser_TitleChanged;
WebBrowser.AddressChanged -= WebBrowser_AddressChanged;
WebBrowser.LoadingStateChanged -= webBrowser_DocumentCompleted;
}
}
seagate 2012 года на терабайт, при подключении головка бегает туда-сюда некоторое время, затем диск отключается
Диск явно подвергался пыткам во время работы: на блине есть отчётливая царапина и несколько точечных царапин.
Что можно попробовать сделать, чтобы диск запустился и хоть что-то с него попытаться вытащить? Контакты платы уже почищены до блеска
этот диск ни в какой специализированный дорогой сервис относить не будет