Here is my code for refrence
public class ProgressChangedObject
{
public string Asin { get; set; }
public string Title { get; set; }
public DownloadProgress downloadProgress { get; set; }
public ProgressChangedObject(string asin, string title, DownloadProgress progress)
{
Asin = asin;
Title = title;
downloadProgress = progress;
}
}
public record QueueFile(string asin, string name);
public class BlockingCollectionQueue : IDownloadQueue
{
private BlockingCollection<QueueFile> _jobs = new BlockingCollection<QueueFile>();
public volatile List<QueueFile> queueFiles = new List<QueueFile>();
private readonly AudibleApi.Api _api;
private readonly LibraryPath _libraryPath;
private volatile float percentComplete;
private volatile QueueFile? currentJob;
private System.Timers.Timer _timer;
public BlockingCollectionQueue(AudibleApi.Api api, LibraryPath libraryPath)
{
var thread = new Thread(new ThreadStart(OnStart));
thread.IsBackground = true;
thread.Start();
_api = api;
_libraryPath = libraryPath;
_timer = new System.Timers.Timer(500);
_timer.Elapsed += TimerTick;
}
~BlockingCollectionQueue()
{
_timer.Dispose();
}
private void TimerTick(object? sender, System.Timers.ElapsedEventArgs e)
{
if (currentJob != null)
{
ProgressChanged?.Invoke(new ProgressChangedObject(currentJob.asin, currentJob.name, new DownloadProgress() { ProgressPercentage = percentComplete }));
}
}
public event Action<ProgressChangedObject>? ProgressChanged;
public void Enqueue(QueueFile job)
{
_jobs.Add(job);
queueFiles.Add(job);
}
private async void OnStart()
{
foreach (var job in _jobs.GetConsumingEnumerable(CancellationToken.None))
{
_timer.Enabled = true;
var d = new Progress<DownloadProgress>();
EventHandler<DownloadProgress> del = (object? sender, DownloadProgress e) => { if (e.ProgressPercentage is not null) { percentComplete = (float)e.ProgressPercentage; currentJob = job; } };
d.ProgressChanged += del;
await _api.DownloadAsync(job.asin, _libraryPath, new AsinTitlePair(job.asin, job.name), d);
d.ProgressChanged -= del;
_timer.Enabled = false;
queueFiles.Remove(job);
}
}
public List<QueueFile> GetQueue()
{
//MessageBox.Show(_jobs.GetConsumingEnumerable().Count().ToString());
return queueFiles;
}
}
I have an instance of this class in my app and when I need to download something I simply add a new queuefile to the queue, the problem is when I subscribe to the Progress changed event like this :
IDownloadQueue downloadQueue = new BlockingCollectionQueue();
downloadQueue.ProgressChanged += OnQueueChanged;
private void OnQueueChanged(ProgressChangedObject obj)
{
\\ some textblock in my xaml
myTextBlock.Text = obj.Title;
}
It throws this error: Exception thrown: 'System.InvalidOperationException' in WindowsBase.dll An exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll but was not handled in user code The calling thread cannot access this object because a different thread owns it.
How can I fix this?