<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Amedeo</title>
    <description>The latest articles on DEV Community by Amedeo (@amedeov).</description>
    <link>https://dev.to/amedeov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F817152%2F45af9efb-4a5d-405e-a315-af51cc1379f0.jpeg</url>
      <title>DEV Community: Amedeo</title>
      <link>https://dev.to/amedeov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amedeov"/>
    <language>en</language>
    <item>
      <title>Gitleaks Pre-Commit Hook</title>
      <dc:creator>Amedeo</dc:creator>
      <pubDate>Tue, 09 Dec 2025 11:18:36 +0000</pubDate>
      <link>https://dev.to/amedeov/gitleaks-pre-commit-hook-45m3</link>
      <guid>https://dev.to/amedeov/gitleaks-pre-commit-hook-45m3</guid>
      <description>&lt;p&gt;As a software engineer, sometimes when troubleshooting something I need to hardcode passwords locally to connect to DEV environments. Yeah, I could use environment variables and all that... but let's be honest - when you just want to quickly check something, hardcoding it is the fastest way. I know, I'm lazy.&lt;/p&gt;

&lt;p&gt;Specifically, I was trying to verify that a password for connecting to Redis in DEV was correct. After adding it to the code and testing it, I had that sinking feeling about "what if I accidentally commit and push this?" That got me thinking - I really need to automate this check.&lt;/p&gt;

&lt;p&gt;Initially I used TruffleHog and wrote a &lt;a href="https://github.com/AmedeoV/trufflehog-pre-commit-hook" rel="noopener noreferrer"&gt;pre-commit hook script for it&lt;/a&gt;. But after chatting with a few colleagues, they suggested I have a look at Gitleaks instead. The key difference? TruffleHog tries to verify if secrets are actually valid, but that's not what I wanted. Even if something looks like a false positive, I want to be the one who decides that. Gitleaks just flags patterns and lets you deal with it - which is exactly the behavior I needed.&lt;/p&gt;

&lt;p&gt;Now, Gitleaks does offer a &lt;a href="https://github.com/gitleaks/gitleaks?tab=readme-ov-file#pre-commit" rel="noopener noreferrer"&gt;pre-commit setup in their README&lt;/a&gt;, but that involves installing the pre-commit package manager and configuring it per repository. I work with over 100 repos. I need something simple that works globally across all of them, not something I have to set up individually for each project. Yes, I am still lazy..&lt;/p&gt;

&lt;p&gt;So I wrote a script that does it all in one go.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Basically runs Gitleaks before every commit. If it finds something that looks like a secret (API keys, tokens, passwords, whatever), it blocks the commit. Simple.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydqd8to5qlvimgteryem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydqd8to5qlvimgteryem.png" alt="Gitleaks catching a Slack token before it gets committed" width="584" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One command to install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sSL https://raw.githubusercontent.com/AmedeoV/gitleaks-pre-commit-hook/refs/heads/main/gitleaks-local-git-pre-hook.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it just works everywhere. All repos, automatically protected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I like it
&lt;/h2&gt;

&lt;p&gt;I don't have to think about it. That's the whole point. I code, I commit, if there's something sensitive in there, it stops me. Done.&lt;/p&gt;

&lt;p&gt;It detects like 100+ different types of secrets out of the box. You can add custom rules too if you have specific patterns you want to catch.&lt;/p&gt;

&lt;h2&gt;
  
  
  One small annoyance
&lt;/h2&gt;

&lt;p&gt;Sometimes it flags false positives. But you can bypass with &lt;code&gt;--no-verify&lt;/code&gt; when you're sure it's safe. Haven't needed to do that often though.&lt;/p&gt;

&lt;p&gt;Already saved me twice from pushing stuff I shouldn't. Feels good knowing it's there watching.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Link: &lt;a href="https://github.com/AmedeoV/gitleaks-pre-commit-hook" rel="noopener noreferrer"&gt;github.com/AmedeoV/gitleaks-pre-commit-hook&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>security</category>
      <category>git</category>
      <category>bash</category>
      <category>automation</category>
    </item>
    <item>
      <title>🔎 Seraphix: The Scanner Toolkit That Led to F5 Security Researcher Recognition</title>
      <dc:creator>Amedeo</dc:creator>
      <pubDate>Wed, 08 Oct 2025 15:14:32 +0000</pubDate>
      <link>https://dev.to/amedeov/seraphix-the-secret-scanner-toolkit-built-for-speed-scale-and-bug-bounties-5f0l</link>
      <guid>https://dev.to/amedeov/seraphix-the-secret-scanner-toolkit-built-for-speed-scale-and-bug-bounties-5f0l</guid>
      <description>&lt;p&gt;I'm excited to introduce &lt;strong&gt;Seraphix&lt;/strong&gt;, a comprehensive, open-source secret scanning toolkit I built to meet the needs of serious security researchers and bug bounty hunters.&lt;/p&gt;

&lt;p&gt;Seraphix is designed for &lt;strong&gt;speed and scale&lt;/strong&gt;, moving far beyond basic repository checks. It integrates multiple powerful scanning strategies—from organization-wide audits to finding data thought to be deleted forever—all managed through an efficient, customizable workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Seraphix Core Capabilities: Beyond the Basics
&lt;/h2&gt;

&lt;p&gt;Seraphix is built on four core pillars, giving you flexibility and power for any audit scenario:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Massive-Scale Organization Scanning
&lt;/h3&gt;

&lt;p&gt;Seraphix can scan an entire list of GitHub organizations or target a single organization, fetching and processing repositories in &lt;strong&gt;parallel&lt;/strong&gt;. It dynamically calculates the optimal number of workers to use on your system, ensuring scans are completed as quickly as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Force-Push Goldmine
&lt;/h3&gt;

&lt;p&gt;This is our unique advantage. When a developer accidentally commits a secret and then performs a &lt;code&gt;git push --force&lt;/code&gt; to delete it, the commit often becomes &lt;strong&gt;"dangling"&lt;/strong&gt; but remains accessible. Seraphix uses a filtered GHArchive dataset to specifically identify these force-pushed commits and uncover secrets that other scanners miss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To check and verify the integrity and validity of every secret found, Seraphix leverages the power of &lt;a href="https://github.com/trufflesecurity/trufflehog" rel="noopener noreferrer"&gt;TruffleHog&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch Seraphix in action, hunting for secrets in a force-pushed commit:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5spmr18uj7b9lj5g9gat.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5spmr18uj7b9lj5g9gat.gif" alt="Seraphix Scanner Demo showing force push secret scanning" width="1115" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;The Inspiration:&lt;/strong&gt; The force-push scanning technique was directly inspired by the groundbreaking work of Sharon Brizinov. You can read the original post detailing how he scanned all of GitHub's "oops" commits and earned bounties here: &lt;a href="https://trufflesecurity.com/blog/guest-post-how-i-scanned-all-of-github-s-oops-commits-for-leaked-secrets" rel="noopener noreferrer"&gt;How I Scanned All of GitHub’s "Oops" Commits for Leaked Secrets&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. The Bug Bounty Utility
&lt;/h3&gt;

&lt;p&gt;Looking for targets? Seraphix includes a powerful utility to fetch and generate lists of GitHub organizations known to offer bug bounty programs. You can then feed this curated list directly into the mass scanning module, streamlining your hunting workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Targeted Repository and Commit Scanning
&lt;/h3&gt;

&lt;p&gt;For focused investigation, you can easily target specific repositories or individual commits for a deep-dive analysis.&lt;/p&gt;




&lt;h2&gt;
  
  
  Analytics and Real-Time Notifications
&lt;/h2&gt;

&lt;p&gt;Discovering secrets is only the first step. Seraphix ensures you can verify and act on your findings instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Dashboard
&lt;/h3&gt;

&lt;p&gt;Every scan generates a powerful, &lt;strong&gt;interactive web dashboard&lt;/strong&gt; for visualization and analysis. It provides an at-a-glance view of:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0590lb539mojsbmq2zxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0590lb539mojsbmq2zxq.png" alt="Seraphix interactive dashboard for visualizing secret scan results" width="800" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secret Statistics:&lt;/strong&gt; Breakdown of secret types (e.g., AWS keys, tokens).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk Assessment:&lt;/strong&gt; Severity and calculated risk associated with each finding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification Status:&lt;/strong&gt; Track which secrets have been verified as active.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced Alerting System
&lt;/h3&gt;

&lt;p&gt;You can enable real-time notifications to be alerted the moment a secret is found, without having to wait for the scan to finish. Seraphix supports instant alerts via:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Telegram&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discord&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Email (Mailgun)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Start: Get Seraphix Running in Minutes
&lt;/h2&gt;

&lt;p&gt;Seraphix is primarily written in &lt;strong&gt;Shell&lt;/strong&gt; and &lt;strong&gt;Python&lt;/strong&gt;, making it highly portable and easy to deploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Clone the repository
git clone https://github.com/AmedeoV/seraphix.git
cd seraphix

# Run the installation script to install dependencies
./install_requirements.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Choose Your Scanner (Example: Organization Scan)
&lt;/h3&gt;

&lt;p&gt;To scan an organization (e.g., Microsoft) for the top 10 most recent repos, using parallel processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd org-scanner/
./scan_org.sh microsoft --max-repos 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;👉 &lt;strong&gt;Check out the full documentation and source code here:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/AmedeoV/seraphix" rel="noopener noreferrer"&gt;AmedeoV/seraphix on GitHub&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🏆 Proven Results and Acknowledgment
&lt;/h2&gt;

&lt;p&gt;The deployment and testing capabilities of Seraphix have been directly instrumental in my vulnerability discovery efforts. This work recently resulted in official acknowledgment by F5 in their &lt;a href="https://my.f5.com/manage/s/article/K75282801#top-of-article-54" rel="noopener noreferrer"&gt;SIRT Security Researcher Acknowledgement&lt;/a&gt; program.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>security</category>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Soak Testing with K6</title>
      <dc:creator>Amedeo</dc:creator>
      <pubDate>Fri, 10 Mar 2023 14:06:18 +0000</pubDate>
      <link>https://dev.to/amedeov/soak-testing-with-k6-h9g</link>
      <guid>https://dev.to/amedeov/soak-testing-with-k6-h9g</guid>
      <description>&lt;h2&gt;
  
  
  What is Soak Testing
&lt;/h2&gt;

&lt;p&gt;A soak test, it's like a load test that runs for an extended period. For the following examples I decided to use K6, an extensible testing tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is useful
&lt;/h2&gt;

&lt;p&gt;Typically with a normal load test, we send a bunch of requests for a short period and monitor how the platform performs. While this may be useful for most scenarios, the typical load test might miss some issues that would come up only when the system is stressed for a &lt;em&gt;long&lt;/em&gt; period. For example, during a major event, we might have a lot of clients using our platform for hours and this might cause problems related to memory leaks, logs filling up the disk space and so on...&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of Web API with a memory leak
&lt;/h2&gt;

&lt;p&gt;The following example has been taken from &lt;a href="https://github.com/dotnet/samples/tree/main/core/diagnostics/DiagnosticScenarios" rel="noopener noreferrer"&gt;Microsoft Diagnostic Samples&lt;/a&gt; - This Web API will cause the target to leak memory (amount specified by {kb}).&lt;/p&gt;

&lt;p&gt;Observe that by hitting the API Endpoint, the memory usage keeps growing (the GC Heap Size (MB) increases)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/20638889/174279774-57b08147-fb59-4c3a-9b6b-2f72f227f94c.mp4" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61n93hfep9ohsuxmutmk.gif" alt="GCHeapSizeIncrease" width="760" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By running a conventional load test for a short period, it returns a 200 so we think that everything it's working as expected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/20638889/174282112-f3bace0e-8b92-4548-bbcb-1c98a333dde7.mp4" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqoi1jkcr2ltdz4jfkmt1.gif" alt="LoadTest" width="1109" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, when we run a Soak Test for a long period, we notice that some of the requests are failing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/20638889/174282071-402ba300-32b2-4d12-9ba2-f933f95566e7.mp4" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvsbb1e2vb9q64fup4mj.gif" alt="SoakTest" width="1115" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Investigating the exceptions we can see what the issue is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this is the full stack trace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kestrel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="n"&gt;Connection&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s"&gt;"0HMHUTUB1JJR6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s"&gt;"0HMHUTUB1JJR6:00000003"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;An&lt;/span&gt; &lt;span class="n"&gt;unhandled&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;thrown&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

      &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OutOfMemoryException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OutOfMemoryException&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;thrown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_Capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddWithResize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;MemoryLeakApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MemoryLeakController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;memleak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int32&lt;/span&gt; &lt;span class="n"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Controllers&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;MemoryLeakController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="nf"&gt;lambda_method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Closure&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ActionMethodExecutor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SyncObjectResultExecutor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IActionResultTypeMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ObjectMethodExecutor&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControllerActionInvoker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvokeActionMethodAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControllerActionInvoker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Scope&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControllerActionInvoker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvokeNextActionFilterAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="n"&gt;End&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="p"&gt;---&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControllerActionInvoker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Rethrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActionExecutedContextSealed&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControllerActionInvoker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Scope&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ControllerActionInvoker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvokeInnerFilterAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="p"&gt;---&lt;/span&gt; &lt;span class="n"&gt;End&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;previous&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="p"&gt;---&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceInvoker&lt;/span&gt;&lt;span class="p"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;InvokeFilterPipelineAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;g__Awaited&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;20_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResourceInvoker&lt;/span&gt; &lt;span class="n"&gt;invoker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="n"&gt;lastTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Scope&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt; &lt;span class="n"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceInvoker&lt;/span&gt;&lt;span class="p"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;InvokeAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;g__Awaited&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;17_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResourceInvoker&lt;/span&gt; &lt;span class="n"&gt;invoker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mvc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceInvoker&lt;/span&gt;&lt;span class="p"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;InvokeAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;g__Awaited&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;17_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResourceInvoker&lt;/span&gt; &lt;span class="n"&gt;invoker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EndpointMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;g__AwaitRequestTask&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;6_0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Endpoint&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="n"&gt;requestTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthorizationMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AspNetCore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kestrel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Internal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HttpProtocol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProcessRequests&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TContext&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;IHttpApplication&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we can see, a conventional load test would have missed the issue (in this case a memory leak) - keep in mind that this was just an example. &lt;/p&gt;

&lt;p&gt;In a real-world scenario, you would want to run a soak test for several hours on a lower environment or even in production if your application can handle it. &lt;/p&gt;

&lt;p&gt;Then set some alerts on whatever monitoring software you use and check out the results to narrow down and fix any issues.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>opensource</category>
      <category>monitoring</category>
      <category>tooling</category>
    </item>
    <item>
      <title>F# - C# Interop</title>
      <dc:creator>Amedeo</dc:creator>
      <pubDate>Thu, 24 Feb 2022 09:52:10 +0000</pubDate>
      <link>https://dev.to/amedeov/f-c-interop-2a42</link>
      <guid>https://dev.to/amedeov/f-c-interop-2a42</guid>
      <description>&lt;h2&gt;
  
  
  What is Interop
&lt;/h2&gt;

&lt;p&gt;Interoperability is the ability of two different systems to communicate with each other. In this case, it would be a C# and F# application communicating.  Because they compile down to the same Intermediate Language we can reference F# projects in C# projects and vice versa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this useful
&lt;/h2&gt;

&lt;p&gt;One of the benefits is that if you are planning to migrate your codebase from C# to F#, you can do it gradually by introducing some F# code without discarding any of the existing code base.&lt;/p&gt;

&lt;p&gt;Sometimes we want to take advantage of the C# world, i.e. a lot of existing nuget packages are written in C# and we don't want to rewrite them in F#.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Please note that all the observations listed on this page are valid for .NET 5 and below.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Example F# Application using C# library
&lt;/h2&gt;

&lt;p&gt;In this example, we are going to create an F# application that uses a C# library. &lt;/p&gt;

&lt;p&gt;The library simulates an IO operation with &lt;code&gt;await Task.Delay(300, cancellationToken);&lt;/code&gt; and reverses the words sent.&lt;/p&gt;

&lt;h3&gt;
  
  
  C# Library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;WordReverserLibraryCsharp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WordReverser&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;WordReverserAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  F# Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nc"&gt;WordReverserConsoleAppFsharp&lt;/span&gt;

&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Threading&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;WordReverserLibraryCsharp&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;WordReverserModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;wordReverser&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;reversedWords&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="nn"&gt;WordReverser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WordReverserAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AwaitTask&lt;/span&gt;
            &lt;span class="n"&gt;printfn&lt;/span&gt; &lt;span class="o"&gt;($&lt;/span&gt;&lt;span class="s2"&gt;"{reversedWords}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wordReverser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"one two three"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;        
    &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RunSynchronously&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;To consume the C# library from F#, we have to convert the &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt;returned from the library to &lt;code&gt;Async&amp;lt;T&amp;gt;&lt;/code&gt; using &lt;code&gt;Async.AwaitTask&lt;/code&gt; which waits for the Task to complete and returns its result as &lt;code&gt;Async&amp;lt;T&amp;gt;&lt;/code&gt;.  &lt;a href="https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/async#asyncawaittask" rel="noopener noreferrer"&gt;Read about Async.AwaitTask here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just before the line &lt;code&gt;Async.Start(wordReverser("one two three"))&lt;/code&gt; we still haven't invoked the operation, only done the setup to call &lt;code&gt;wordReverser&lt;/code&gt;, to start the operation we can use &lt;code&gt;Async.Start(wordReverser("one two three")&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example C# Application using F# library
&lt;/h2&gt;

&lt;p&gt;In this example we are doing the opposite of the previous one: we create a C# application that uses an F# library.&lt;/p&gt;

&lt;h3&gt;
  
  
  F# Library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nc"&gt;WordReverserLibraryFsharp&lt;/span&gt;

&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Threading&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Tasks&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;WordReverserModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;wordReverser&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reverser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="k"&gt;return&lt;/span&gt;
                    &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Split&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt; &lt;span class="p"&gt;|]&lt;/span&gt;
                    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rev&lt;/span&gt;
                    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StartAsTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;TaskCreationOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  C# Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;WordReverserLibraryFsharp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;WordReverserConsoleAppCsharp&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reversedWords&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;WordReverserModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wordReverser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"one two three"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reversedWords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;We can't use F# &lt;code&gt;Async&lt;/code&gt; in C#, but the F# library can return a &lt;code&gt;Task&lt;/code&gt; so that the C# application can consume it without any issues. We can achieve this by using &lt;code&gt;Async.StartAsTask&lt;/code&gt; in .NET 5 and below.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/async#asyncstartastask" rel="noopener noreferrer"&gt;Read about Async.StartAsTask here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's good practice for any &lt;code&gt;Async&lt;/code&gt; work in C#, to always pass a CancellationToken as an argument, while the F# code does not necessarily need one as the CancellationToken propagation is controlled by how the asynchronous work is kicked off and as a result, CancellationTokens may or may not be propagated. For example &lt;code&gt;Async.Sleep&lt;/code&gt; doesn't accept a CancellationToken as a parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example C# Application using F# library handling exceptions
&lt;/h2&gt;

&lt;p&gt;In this example, we are going to use an F# library from a C# application, handling exceptions and passing a CancellationToken.&lt;/p&gt;

&lt;h3&gt;
  
  
  F# Library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nc"&gt;FsharpLibraryComplete&lt;/span&gt;

&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Threading&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;Threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Tasks&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nc"&gt;FsharpLibraryCompleteModule&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;wordReverser&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raiseException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;CancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reverser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raiseException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
                    &lt;span class="n"&gt;raise&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"wordReverser threw Exception"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;
                    &lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Split&lt;/span&gt; &lt;span class="p"&gt;[|&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt; &lt;span class="k"&gt;'&lt;/span&gt; &lt;span class="p"&gt;|]&lt;/span&gt;
                    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rev&lt;/span&gt;
                    &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concat&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nn"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StartAsTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reverser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;TaskCreationOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  C# Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;FsharpLibraryComplete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;ConsoleAppCsharpComplete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;reversedWords&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="n"&gt;reversedWords&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;FsharpLibraryCompleteModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wordReverser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"one two three"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reversedWords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Console output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.Exception: someAsyncFunction threw Exception
   at FsharpLibraryComplete.FsharpLibraryCompleteModule.wordReverser@12-1.Invoke(Unit _arg1) in C:\projects\InteropPlayGround\Docker\ConsoleAppCsharpComplete\FsharpLibraryComplete\FsharpLibraryComplete.fs:line 13
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 464
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 104
--- End of stack trace from previous location ---
   at ConsoleAppCsharpComplete.Program.Main() in C:\projects\InteropPlayGround\Docker\ConsoleAppCsharpComplete\ConsoleAppCsharpComplete\Program.cs:line 14
Unhandled exception. System.Exception: someAsyncFunction threw Exception
   at FsharpLibraryComplete.FsharpLibraryCompleteModule.wordReverser@12-1.Invoke(Unit _arg1) in C:\projects\InteropPlayGround\Docker\ConsoleAppCsharpComplete\FsharpLibraryComplete\FsharpLibraryComplete.fs:line 13
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 464
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in D:\a\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 104
--- End of stack trace from previous location ---
   at ConsoleAppCsharpComplete.Program.Main() in C:\projects\InteropPlayGround\Docker\ConsoleAppCsharpComplete\ConsoleAppCsharpComplete\Program.cs:line 14
   at ConsoleAppCsharpComplete.Program.&amp;lt;Main&amp;gt;()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;Running the code as it is, will raise an exception from the F# library that gets caught by the C# application.&lt;/p&gt;

&lt;p&gt;Please note that if the Task gets cancelled before raising the exception on the F# library, the C# application will catch the exception as &lt;code&gt;System.Threading.Tasks.TaskCanceledException: A task was canceled.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It's not particularly difficult to use F# libraries in a C# application and vice versa, but there are a few things that we have to keep in mind, i.e. C# does not work with F# &lt;code&gt;Async&lt;/code&gt;, instead, we have to add additional steps to convert &lt;code&gt;Async&lt;/code&gt; into a &lt;code&gt;Task&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>fsharp</category>
      <category>programming</category>
      <category>beginners</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
