Task that ReadsKey from keyboard doesnt work - Consumer/Producer Pattern - c#

I am implementing a single Producer/Consumer Pattern using BlockingCollection.
When i click 'c' from keyboard i want to cancel the operation using CancellationToken.
The strange thing is that if i press 'c' as fast as i can after i run the program, the program listen to the event.
If i click 'c' later lets say at 45000th iteration the program doesnt react.
I have a for loop that populates the producer.
for (int i = 0; i < 50000; i++)
{
logger.AddToQueue("Number with flush " + i, true);
}
logger.DataItems.CompleteAdding();
At the constructor of logger i call this method:
private Task t;
public void KeyPress()
{
t = Task.Run(() =>
{
if (Console.ReadKey(true).KeyChar == 'c')
{
cts.Cancel();
}
});
}
I dont know if the error is relevant to the other methods but i will post them just in case:
The addToQueue (Producer):
public void AddToQueue(String text, bool isFlushOn) {
Consumer(isFlushOn);
try {
_dataItems.TryAdd(new LogLine() { Text = text, Timestamp = DateTime.Now }, 0, ct);
} catch (OperationCanceledException) {
_dataItems.CompleteAdding();
}
}
and the consumer:
Task task = null;
public void Consumer(bool isStopWithFlushOn)
{
if (task == null)
{
task = Task.Run(() =>
{
while (!_dataItems.IsCompleted) {
try {
LogLine data = null;
if (!_dataItems.TryTake(out data, 5, ct)) {
Console.WriteLine(" Take Blocked");
} else {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(data.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"));
stringBuilder.Append("\t");
stringBuilder.Append(data.LineText());
stringBuilder.Append("\t");
_writer.WriteLine(stringBuilder.ToString());
Console.WriteLine(" Take:{0}", data.Text);
}
} catch (OperationCanceledException) {
if (isStopWithFlushOn) {
Console.WriteLine("Canceled with flush.");
foreach (var dataItem in _dataItems.GetConsumingEnumerable()) {
Console.WriteLine("Canceled Take:{0}", dataItem.Text);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(dataItem.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"));
stringBuilder.Append("\t");
stringBuilder.Append("Number with flush " + dataItem.LineText());
stringBuilder.Append("\t");
_writer.WriteLine(stringBuilder.ToString());
Thread.SpinWait(500000);
}
} else {
Console.WriteLine("Canceled without flush.");
break;
}
}
}
Console.WriteLine("\r\nNo more items to take.");
});
}
}

Related

create multiple files using multiple threads c#

I am creating console app to simulate server. I create multiple virus files together using multiple threads to see whether all files get quarantined, if yes, how long it takes to quarantined. The problem with multithreading application is one thread starts writing another thread so I get exception - The process can not access the file X because the file is being used by another process. This is the reason that all files don't get quarantined. I use framework 4.5.2
I have created app using thread and task. I don't get the desire result. What is the best practice to write this app? Thank you for helping me in advance.
Using Thread:
class Program
{
static string folderPath;
static readonly string fileContent = #"X5O!P%#AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
static void Main(string[] args)
{
folderPath = "F:\VirusScan";
int counter = 1000;
for (int i = 0; i < counter; i++)
{
var thread = new Thread(() => GenerateVirusFile(i));
thread.Start();
}
Console.ReadKey();
}
static void GenerateVirusFile(int i)
{
string filePath = $#"{folderPath}\TestForVirusScan_{i}_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.txt";
try
{
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(fileContent);
}
var timer = Stopwatch.StartNew();
while (true)
{
if (!File.Exists(filePath))
{
Console.WriteLine($"{i}: File was removed in {timer.ElapsedMilliseconds}ms");
break;
}
else
{
Thread.Sleep(1);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"{i}: Exception {ex.GetType().Name} occurred: {ex.Message}");
}
}
}
Using Task:
class Program
{
static string folderPath;
static readonly string fileContent = #"X5O!P%#AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
static void Main(string[] args)
{
folderPath = "F:\VirusScan";
int counter = 1000;
List<Task> tasks = new List<Task>();
for (int i = 1; i <= counter; i++)
{
Task newTask = new Task((x) => GenerateVirusFile(x), i);
tasks.Add(newTask);
}
foreach (var task in tasks)
{
task.Start();
}
Task.WaitAll(tasks.ToArray());
Console.ReadKey();
}
public static void GenerateVirusFile(object i)
{
string filePath = $#"{folderPath}\TestForVirusScan_{i}_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.txt";
try
{
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(fileContent);
}
var timer = Stopwatch.StartNew();
while (true)
{
if (!File.Exists(filePath))
{
Console.WriteLine($"{i}: File was removed in {timer.ElapsedMilliseconds}ms");
break;
}
else
{
Thread.Sleep(1);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"{i}: Exception {ex.GetType().Name} occurred: {ex.Message}");
}
}
}
The problem is in the following code:
for (int i = 0; i < counter; i++)
{
var thread = new Thread(() => GenerateVirusFile(i));
thread.Start();
}
The closure () => GenerateVirusFile(i) is referencing changing variable
Rewrite it in the following way:
Parallel.For(0, counter, GenerateVirusFile);
Have you tried something like this in your loop:
int x = i;
var thread = new Thread(() => GenerateVirusFile(x));
this prevents that the same i is used for more threads/file names.

NetMQ Polling a rep socket with a timeout in a loop

I'm trying to port my code from an obsolete library called CastleMQ to NetMQ but I'm running into some problems.
I prefer to using polling with a timeout, for reliability - I just found that it worked best for me from trial and error compared to just sitting blocking the port indefinitely.
here is my CastleMQ code
public int ZeroPort;
private void ThreadProc()
{
var ctx = new Context();
try {
using (var repSocket = ctx.CreateSocket(SocketType.Rep))
{
string bindAddress = "tcp://*:"+ZeroPort;
repSocket.Bind(bindAddress);
print2("*** BINDING on {0} ***", bindAddress);
bool quit = false;
while (!quit) {
try {
var polling = new Polling(PollingEvents.RecvReady, repSocket);
polling.RecvReady += (socket) =>
{ // using socket.Recv() here is guaranted to return stuff
var msg = socket.Recv();
var msgStr = Encoding.UTF8.GetString(msg);
print2("[REP:{0}] {1}", bindAddress, msgStr);
switch (msgStr) {
case "positions": {
StringBuilder csv = new StringBuilder();
print2("csv: {0}", csv.ToString());
socket.Send(csv.ToString());
break;
}
default: {
socket.Send("Unrecognized Command: " + msgStr);
break;
}
}
};
polling.Poll(POLL_TIMEOUT_MS); // this returns once some socket event happens
} catch (Exception e) {
if (e is ThreadAbortException) {
quit = true;
print2("\n*** EXITED ***");
} else print2(e.ToString());
}
}
}
} catch (Exception e) {
print2(e.ToString());
} finally {
ctx.Dispose();
}
}
here is what I tried to do and then got lost with NetMQ
private void ThreadProc()
{
try {
string bindAddress = "#tcp://*:" + ZeroPort;
print2("*** BINDING on {0} ***", bindAddress);
using (var repSocket = new ResponseSocket(bindAddress))
using (var poller = new NetMQPoller { repSocket })
{
// bool quit = false;
// while (!quit)
// these event will be raised by the Poller
repSocket.ReceiveReady += (s, a) =>
{
// receive won't block as a message is ready
string msg = a.Socket.ReceiveString(); // defeinition for ReceiveString() can't be found
// send a response
a.Socket.Send("Response"); // it doesn't like "Response", do I need to wrap it in some object?
I'm especially confused as how to add a timeout so I can poll with a timeout in a loop the way my CastleMQ code does.
Any pointers would be much appreciated, thanks

Adding and Removing Items when having new process C#

Hi everyboy I have some problem with Multi Thread and ListView Update:
I want to list running process by name in a Listview, and removing when this process close. But my code just adding a new process and dont remove when the process close. I am a beginner user in C#. Thank you.
*** I dont want to use listview.Clear() cause Im going to make a bot with multi client
Here's my code:
bool status = true;
int[] PID = new int[10];
Memory Mem = new Memory();
private void startChecking()
{
while (status)
{
try
{
int count = 0;
Process[] processes = Process.GetProcessesByName("notepad");
if (processes.Length > 0)
{
if (listAccount.Items.Count < processes.Length)
{
foreach (Process process in processes)
{
if (listAccount.Items.Count < processes.Length && PID[count] != process.Id)
{
Mem.SetTitle(process.MainWindowHandle, "Cyber Auto - " + count.ToString());
AddItemNew(process.MainWindowTitle);
PID[count] = process.Id;
}
count++;
}
}
else if (listAccount.Items.Count < processes.Length)
{
}
}
Thread.Sleep(1000);
}
catch (Exception ex)
{
MessageBox.Show("Somethine went wrong : " + ex.ToString());
}
}
}
Here is my AddItemNew / RemoveItem methods:
private delegate void dlgAddItemNew(string i);
private void AddItemNew(string i)
{
if (this.listAccount.InvokeRequired)
{
this.Invoke(new dlgAddItemNew(AddItemNew), i);
}
else
{
ListViewItem accountAdd = new ListViewItem(i);
accountAdd.SubItems.Add("0");
accountAdd.SubItems.Add("0");
accountAdd.SubItems.Add("0");
accountAdd.SubItems.Add("0");
this.listAccount.Items.Add(accountAdd);
}
}
private delegate void dlgRemoveItem(int i);
private void RemoveItem(int i)
{
if (this.listAccount.InvokeRequired)
{
this.Invoke(new dlgRemoveItem(RemoveItem), i);
}
else
{
this.listAccount.Items[i].Remove();
}
}
P/S : Sorry If my Enlish is not good....
If you want to check at periodic interval, then you can clear the ListView before populating it again. (This is what Captain0 meant in his comments above)
I have modified your code a bit and I can see it working when I open/close instance of notepad, it update the count, No need for separate add/remove items (unless you had to something different in opening & closing of notepad process)
private void startChecking()
{
while (status)
{
try
{
Process[] processes = Process.GetProcessesByName("notepad");
UpdateListView(processes.Count());
Thread.Sleep(2000);
}
catch (Exception ex)
{
MessageBox.Show("Somethine went wrong : " + ex.ToString());
status = false;
}
}
}
private void UpdateListView(int processCount)
{
if (listView1.InvokeRequired)
{
Action action = () => UpdateListView(processCount);
Invoke(action);
}
else
{
listView1.Items.Clear(); // Clearing the List view before adding them again
for (int i = 0; i < processCount; i++)
{
ListViewItem accountAdd = new ListViewItem(i.ToString());
listView1.Items.Add(accountAdd);
}
}
}

Check tag for content with Overwrite warning

void device_DeviceArrived(ProximityDevice sender)
{
//Compatible Device enters area
if (stance == WriteStage.PREP)
{
System.Diagnostics.Debug.WriteLine("Writestages won");
//Perhaps here
updateStatusRectangle(Colors.Yellow);
stance = WriteStage.WRITING;
updateStatusText("Writing...");
writeToTag(msg);
}
else
{
updateReceivedText("Device connected!");
}
}
private void MessageReceivedHandler(ProximityDevice sender, ProximityMessage message)
{
System.Diagnostics.Debug.WriteLine("Handler ran");
var rawMsg = message.Data.ToArray();
var ndefMessage = NdefMessage.FromByteArray(rawMsg);
foreach (NdefRecord record in ndefMessage)
{
System.Diagnostics.Debug.WriteLine("Record type: " + Encoding.UTF8.GetString(record.Type, 0, record.Type.Length));
var specType = record.CheckSpecializedType(false);
if (specType == typeof(NdefTextRecord))
{
var textrec = new NdefTextRecord(record);
updateReceivedText(textrec.Text);
}
}
}
The above event and handler are executed when the phone comes into contact with an NFC device. For intents and purposes in this app, I need to ensure that before writing to a card, if it already has content, it will prompt the user to verify overwriting the data. I commented where I think it should go, but as far as checking for the Message, I'm not sure how to go about it. I can't call the handler without the ProximityMessage, and I don't know of another way to view the message.
The Question: Is it possible to call the MessageReceivedHandler (or check the message at all), from device_DeviceArrived?
(Note: Debug.Writelines are for test purposes, and this is just a quick NFC writer I'm throwing together).
UPDATE: In attempting to find a work around, I ran into a different problem.
public bool promptUserForOverwrite()
{
bool response = false;
Dispatcher.BeginInvoke(() =>
{
MessageBoxResult cc = MessageBox.Show("You are about to overwrite data. Proceed?", "Overwrite?", MessageBoxButton.OKCancel);
if (cc == MessageBoxResult.OK)
{
System.Diagnostics.Debug.WriteLine("MessageBox OK result");
response = true;
}
});
return response;
}
private void MessageReceivedHandler(ProximityDevice sender, ProximityMessage message)
{
System.Diagnostics.Debug.WriteLine("Handler ran");
var rawMsg = message.Data.ToArray();
var ndefMessage = NdefMessage.FromByteArray(rawMsg);
foreach (NdefRecord record in ndefMessage)
{
System.Diagnostics.Debug.WriteLine("Record type: " + Encoding.UTF8.GetString(record.Type, 0, record.Type.Length));
var specType = record.CheckSpecializedType(false);
if (specType == typeof(NdefTextRecord))
{
var textrec = new NdefTextRecord(record);
updateReceivedText(textrec.Text);
}
}
bool pow = promptUserForOverwrite();
if (!pow)
{
System.Diagnostics.Debug.WriteLine("Prompt returned");
//This always hits - pow is always false.
}
if (stance == WriteStage.WRITING && pow)
{
//writeToTag(msg);
}
}
This would work as a work around; the problem is the beginInvoke method. I need it for cross thread access, but used like this seems to make it run at a later time (when the thread is free?). The bool pow is always false, even after I click ok on the messagebox (debugged, and it does get the result, but after I can no longer use it). Is there an alternative that I can use for the Dispatcher?
Ugly, but I have this working. You need to get a TaskScheduler from the UI thread, so declare a
private TaskScheduler sched;
and then on the OnLoaded event for the page
sched = TaskScheduler.FromCurrentSynchronizationContext();
Then your methods
public async Task<bool> promptUserForOverwrite()
{
return false;
}
private async void MessageReceivedHandler(ProximityDevice sender, ProximityMessage message)
{
System.Diagnostics.Debug.WriteLine("Handler ran");
var rawMsg = message.Data.ToArray();
var ndefMessage = NdefMessage.FromByteArray(rawMsg);
foreach (NdefRecord record in ndefMessage)
{
System.Diagnostics.Debug.WriteLine("Record type: " + Encoding.UTF8.GetString(record.Type, 0, record.Type.Length));
var specType = record.CheckSpecializedType(false);
if (specType == typeof(NdefTextRecord))
{
var textrec = new NdefTextRecord(record);
updateReceivedText(textrec.Text);
}
}
var task = promptUserForOverwrite();
var pow = await task.ContinueWith(t =>
{
MessageBoxResult cc = MessageBox.Show("You are about to overwrite data. Proceed?", "Overwrite?", MessageBoxButton.OKCancel);
if (cc == MessageBoxResult.OK)
{
System.Diagnostics.Debug.WriteLine("MessageBox OK result");
return true;
}
else
{
return false;
}
}, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, sched);
if (!pow)
{
System.Diagnostics.Debug.WriteLine("Prompt returned");
//This always hits - pow is always false.
}
if (stance == WriteStage.WRITING && pow)
{
//writeToTag(msg);
}
}

WinRT - MessageDialog.ShowAsync will throw UnauthorizedAccessException in my custom class

I Want to write my own control, when the ctor is invoked, a MessageBox is shown.
public class Class1
{
public Class1()
{
ShowDialog();
}
void ShowDialog()
{
SynchronizationContext context = SynchronizationContext.Current;
if (context != null)
{
context.Post((f) =>
{
MessageDialog dialog = new MessageDialog("Hello!");
dialog.ShowAsync();
}, null);
}
}
}
If my class is used by someone, and write the codes as below, UnauthorizedAccessException is always thrown in dialog.ShowAsync();
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
ClassLibrary1.Class1 c1 = new ClassLibrary1.Class1();
MessageDialog dialog1 = new MessageDialog("");
dialog1.ShowAsync();
}
Is there a way to show a message dialog without exception?
I found a way, enjoy it!
Task ShowDialog()
{
CoreDispatcher dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
Func<object, Task<bool>> action = null;
action = async (o) =>
{
try
{
if (dispatcher.HasThreadAccess)
await new MessageDialog("Hello!").ShowAsync();
else
{
dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() => action(o));
}
return true;
}
catch (UnauthorizedAccessException)
{
if (action != null)
{
Task.Delay(500).ContinueWith(async t => await action(o));
}
}
return false;
};
return action(null);
}
As MessageDialogue needs to run on the UI thread, can you try switching it to:
var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
dispatcher.RunAsync(DispatcherPriority.Normal, <lambda for your code which should run on the UI thread>);
The cleaner solution may look like this. The interesting part ist hidden in die showDialogAsync(). For convenience you can use the Close() method to close the current dialog again programmatically. The IUIDispatcher is another helper interface you can rebuild yourself easily:
private readonly IUIDispatcher _dispatcher;
readonly Object _queueMonitor = new object();
readonly Object _showMonitor = new object();
private IAsyncOperation<IUICommand> _currentDialogOperation;
readonly Queue<MessageDialog> _dialogQueue = new Queue<MessageDialog>();
public async Task ShowAsync(string content)
{
var md = new MessageDialog(content);
await showDialogAsync(md);
}
public async Task ShowAsync(string content, string caption)
{
var md = new MessageDialog(content, caption);
await showDialogAsync(md);
}
public async Task<MessageDialogResult> ShowAsync(string content, MessageDialogType dialogType)
{
var messageDialogResult = await ShowAsync(content, null, dialogType);
return messageDialogResult;
}
public async Task<MessageDialogResult> ShowAsync(string content, string caption, MessageDialogType dialogType)
{
var result = MessageDialogResult.Ok;
var md = string.IsNullOrEmpty(caption) ? new MessageDialog(content) : new MessageDialog(content, caption);
switch (dialogType)
{
case MessageDialogType.Ok:
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonOk"], command => result = MessageDialogResult.Ok));
md.CancelCommandIndex = 0;
md.DefaultCommandIndex = 0;
break;
case MessageDialogType.OkCancel:
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonOk"], command => result = MessageDialogResult.Ok));
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonCancel"], command => result = MessageDialogResult.Cancel));
md.DefaultCommandIndex = 0;
md.CancelCommandIndex = 1;
break;
case MessageDialogType.YesNo:
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonYes"], command => result = MessageDialogResult.Yes));
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonNo"], command => result = MessageDialogResult.No));
md.DefaultCommandIndex = 0;
md.CancelCommandIndex = 1;
break;
case MessageDialogType.YesNoCancel:
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonYes"], command => result = MessageDialogResult.Yes));
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonNo"], command => result = MessageDialogResult.No));
md.Commands.Add(new UICommand(ResWrapper.Strings["MessageDialogButtonCancel"], command => result = MessageDialogResult.Cancel));
md.DefaultCommandIndex = 0;
md.CancelCommandIndex = 1;
break;
default:
throw new ArgumentOutOfRangeException("dialogType");
}
await showDialogAsync(md);
return result;
}
/// <summary>
/// Shows the dialogs, queued and one after the other.
/// We need this as a workaround for the the UnauthorizedAcsess exception.
/// </summary>
/// <param name="messageDialog">The message dialog.</param>
/// <returns></returns>
async Task showDialogAsync(MessageDialog messageDialog)
{
//Calls this function in a separated task to avoid ui thread deadlocks.
await Task.Run(async () =>
{
lock (_queueMonitor)
{
_dialogQueue.Enqueue(messageDialog);
}
try
{
while (true)
{
MessageDialog nextMessageDialog;
lock (_queueMonitor)
{
if (_dialogQueue.Count > 1)
{
Debug.WriteLine("MessageDialogService.cs | showDialogAsync | Next dialog is waiting for MessageDialog to be accessable!!");
Monitor.Wait(_queueMonitor); //unlock and wait - regains lock after waiting
}
nextMessageDialog = _dialogQueue.Peek();
}
var showing = false;
_dispatcher.Execute(async () =>
{
try
{
lock (_showMonitor)
{
showing = true;
_currentDialogOperation = nextMessageDialog.ShowAsync();
}
await _currentDialogOperation;
lock (_showMonitor)
_currentDialogOperation = null;
}
catch (Exception e)
{
Debug.WriteLine("MessageDialogService.cs | showDialogAsync | " + e);
}
lock (_showMonitor)
{
showing = false;
Monitor.Pulse(_showMonitor); //unlock and wait - regains lock after waiting
}
});
lock (_showMonitor)
{
if (showing)
{
Debug.WriteLine("MessageDialogService.cs | showDialogAsync | Waiting for MessageDialog to be closed!!");
//we must wait here manually for the closing of the dialog, because the dispatcher does not return a waitable task.
Monitor.Wait(_showMonitor); //unlock and wait - regains lock after waiting
}
}
Debug.WriteLine("MessageDialogService.cs | showDialogAsync | MessageDialog was closed.");
return true;
}
}
finally
{
//make sure we leave this in a clean state
lock (_queueMonitor)
{
_dialogQueue.Dequeue();
Monitor.Pulse(_queueMonitor);
}
}
});
}
public void Close(string keyContent="")
{
try
{
if (keyContent.IsNullOrEmpty())
{
lock (_showMonitor)
{
if (_currentDialogOperation == null) return;
_currentDialogOperation.Cancel();
_currentDialogOperation = null;
}
}
else
{
var cancel = false;
lock (_queueMonitor)
{
if (_dialogQueue.Count == 0)
return;
var currentDialog = _dialogQueue.Peek();
Debug.WriteLine("MessageDialogService.cs | Close | {0}", currentDialog.Content);
if (currentDialog.Content == keyContent)
{
cancel = true;
}
}
if (!cancel) return;
lock (_showMonitor)
{
if (_currentDialogOperation == null) return;
_currentDialogOperation.Cancel();
_currentDialogOperation = null;
}
}
}
catch (Exception e)
{
Debug.WriteLine("MessageDialogService.cs | Close | " + e);
}
}
I think I've found it. I had the same problem when creating messageboxes in any other threads besides the main thread.
This is the C++ solution but I think you can convert it easily ;)
IAsyncOperation<IUICommand^> ^Op = msgbox->ShowAsync();
task<IUICommand^>( Op ).then([=](IUICommand^ C)
{
}).then([](task<void> t)
{
try
{
t.get();
}
catch (Platform::Exception ^e)
{
//ERROR!
}
});
On a side note this is the correct way to handle ANY WinRT/Windows 8 Store C++ exception.
You can always use
Execute.OnUIThread( async () => {
...
var dialog = new MessageDialog(yourMessage);
await dialog.ShowAsync();
...
});
This doesn't solve race conditions in the UI if you are trying to launch multiple dialogs from background threads. But you could use a try/catch to make sure you cover for that case.

Categories

Resources