{"id":90743,"date":"2020-10-16T16:00:45","date_gmt":"2020-10-16T13:00:45","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/"},"modified":"2020-10-16T16:00:45","modified_gmt":"2020-10-16T13:00:45","slug":"how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/","title":{"rendered":"#How To Multithread Safely and Efficiently in .NET \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a29e8d72c0f2\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a29e8d72c0f2\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/#What_Makes_Multithreading_Hard\" >What Makes Multithreading Hard?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/#Use_Interlocked_For_Atomic_Operations\" >Use Interlocked For Atomic Operations<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/#Use_Thread_Safe_Collections\" >Use Thread Safe Collections<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/#Look_to_Parallelize_Loops\" >Look to Parallelize Loops<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-multithread-safely-and-efficiently-in-net-cloudsavvy-it\/#Unity_Multithreading\" >Unity Multithreading<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How To Multithread Safely and Efficiently in .NET \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-6018\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/d9bee69b242da6fb57907d0799a9fdf4\/p\/uploads\/2020\/08\/b476fc9b.png\" alt=\"\" width=\"700\" height=\"300\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Multithreading can be used to drastically speed up the performance of your <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>lication, but no speedup is free\u2014managing parallel threads requires careful programming, and without the proper precautions, you can run into race conditions, deadlocks, and even crashes.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"What_Makes_Multithreading_Hard\"><\/span>What Makes Multithreading Hard?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Unless you tell your program otherwise, all of your code executes on the \u201cMain Thread.\u201d From the entrypoint of your application, it runs through and executes all your functions one after another. This has a limit to performance, since obviously you can only do so much if you have to process everything one at a time.\u00a0Most modern CPUs have six or more cores with 12 or more threads, so there\u2019s performance left on the table if you\u2019re not utilizing them.<\/p>\n<p>However, it\u2019s not as simple as just \u201cturning on multithreading.\u201d Only specific things (such as loops) can be properly multithreaded, and there\u2019s a lot of considerations to take into account when doing so.<\/p>\n<p>The first and most important issue is\u00a0<strong>race conditions<\/strong>. These often occur during write operations, when one thread is modifying a resource that is shared by multiple threads. This leads to behavior where the output of the program depends on which thread finishes or modifies something first, which can lead to random and unexpected behavior.<\/p>\n<p>These can be very, very simple\u2014for example, maybe you need to keep a running count of something between the loops. The most obvious way to do this is creating a variable and incrementing it, but this isn\u2019t thread safe.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7375\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/c283dbd21fb3c1316482df22258de72c\/p\/uploads\/2020\/10\/82bd5b2a.png\" alt=\"\" width=\"530\" height=\"197\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>This race condition occurs because it\u2019s not just \u201cadding one to the variable\u201d in an abstract sense; the CPU is loading the value of <code>number<\/code>\u00a0into the register, adding one to that value, and then storing the result as the new value of the variable. It doesn\u2019t know that, in the meantime, another thread was also trying to do exactly the same, and loaded an soon-to-be incorrect value of <code>number<\/code>. The two threads conflict, and at the end of the loop, <code>number<\/code>\u00a0may not be equal to 100.<\/p>\n<p>.NET provides a feature to help manage this: the <code>lock<\/code>\u00a0keyword. This doesn\u2019t prevent making changes outright, but it helps manage concurrency by only allowing one thread at a time to obtain the lock. If another thread tries to enter a lock statement while another thread is processing, it will wait for up to 300ms before proceeding.<\/p>\n<p>You\u2019re only able to lock reference types, so a common pattern is creating a lock object beforehand, and using that as a substitute to locking the value type.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7376\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/82ef2d27cbaf28362102e7c71cf8d986\/p\/uploads\/2020\/10\/cf59b66a.png\" alt=\"\" width=\"526\" height=\"280\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>However, you may notice that there\u2019s now another problem:\u00a0<strong>deadlocks<\/strong>. This code is a worst case example, but here, it\u2019s almost exactly the same as just doing a regular <code>for<\/code>\u00a0loop (actually a bit slower, since extra threads and locks are extra overhead). Each thread tries to obtain the lock, but only one at a time can have the lock, so only one thread at a time can actually run the code inside the lock. In this case, that\u2019s the entire code of the loop, so the lock statement is removing all the benefit of threading, and just making everything slower.<\/p>\n<p><a href=\"https:\/\/buradabiliyorum.com\/en\/category\/general\/\" data-internallinksmanager029f6b8e52c=\"3\" title=\"General\" target=\"_blank\" rel=\"noopener\">General<\/a>ly, you want to lock as needed whenever you need to make writes. However, you\u2019ll want to keep concurrency in mind when choosing what to lock, because reads aren\u2019t always thread safe either. If another thread is writing to the object, reading it from another thread can give an incorrect value, or cause a particular condition to return an improper result.<\/p>\n<p>Luckily, there are a few tricks to doing this properly where you can balance the speed of multithreading while using locks to avoid race conditions.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Use_Interlocked_For_Atomic_Operations\"><\/span>Use Interlocked For Atomic Operations<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>For basic operations, using the <code>lock<\/code>\u00a0statement can be overkill. While it\u2019s very useful for locking before complex modifications, it\u2019s too much overhead for something as simple as adding or replacing a value.<\/p>\n<p><a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.threading.interlocked%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\">Interlocked<\/a>\u00a0is a class that wraps some memory operations like addition, replacing, and comparision. The underlying methods are implemented at the CPU level and guaranteed to be atomic, and much faster than the standard <code>lock<\/code>\u00a0statement. You\u2019ll want to use them whenever possible, though they won\u2019t entirely replacing locking.<\/p>\n<p>In the example above, replacing the lock with a call to <code>Interlocked.Add()<\/code>\u00a0will speed up the operation a lot. While this simple example isn\u2019t faster than just not using Interlocked, it\u2019s useful as a part of a larger operation and is still a speedup.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7389\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/f387018a2ddd5c7582fb453f7d8622a4\/p\/uploads\/2020\/10\/9a726170.png\" alt=\"\" width=\"443\" height=\"156\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>There\u2019s also <code>Increment<\/code>\u00a0and <code>Decrement<\/code>\u00a0for <code>++<\/code>\u00a0and <code>--<\/code>\u00a0operations, which will save you a solid two keystrokes. They literally wrap <code>Add(ref count, 1)<\/code>\u00a0under the hood, so there\u2019s no specific speedup to using them.<\/p>\n<p>You can also use <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.threading.interlocked.exchange%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\">Exchange<\/a>, a generic method that will set a variable equal to the value passed to it. Though, you should be careful with this one\u2014if you\u2019re setting it to a value you computed using the original value, this isn\u2019t thread safe, since the old value could have been modified before running Interlocked.Exchange.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7391\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/64f0e8c02ecc34df287b9236a18b7448\/p\/uploads\/2020\/10\/e66474c7.png\" alt=\"\" width=\"480\" height=\"188\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p><a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.threading.interlocked.compareexchange%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\">CompareExchange<\/a> will check two values for equality, and replace the value if they\u2019re equal.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Use_Thread_Safe_Collections\"><\/span>Use Thread Safe Collections<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The default collections in <code>System.Collections.Generic<\/code> can be used with multithreading, but they aren\u2019t entirely thread safe. Microsoft <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fstandard%2Fcollections%2Fthread-safe%2F&amp;key=204a528a336ede4177fff0d84a044482\">provides thread-safe implementations of some collections in <code>System.Collections.Concurrent<\/code><\/a>.<\/p>\n<p>Among these include the <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.concurrent.concurrentbag-1%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\"><code>ConcurrentBag<\/code><\/a>, an unordered generic collection, and <code><a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.concurrent.concurrentdictionary-2%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\">ConcurrentDictionary<\/a>,<\/code> a thread-safe Dictionary. There\u2019s also <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.concurrent.concurrentqueue-1%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\">concurrent queues and stacks<\/a>, and <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fapi%2Fsystem.collections.concurrent.orderablepartitioner-1%3Fview%3Dnetcore-3.1&amp;key=204a528a336ede4177fff0d84a044482\"><code>OrderablePartitioner<\/code><\/a>, which can split orderable data sources like Lists into separate partitions for each thread.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Look_to_Parallelize_Loops\"><\/span>Look to Parallelize Loops<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Often, the easiest place to multithread is in big, expensive loops. If you can execute multiple options in parallel, you can get a huge speedup in the overall running time.<\/p>\n<p>The best way to handle this is with <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"http:\/\/redirect.viglink.com?u=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fdotnet%2Fstandard%2Fparallel-programming%2Fdata-parallelism-task-parallel-library&amp;key=204a528a336ede4177fff0d84a044482\"><code>System.Threading.Tasks.Parallel<\/code>.<\/a>\u00a0This class provides replacements for <code>for<\/code>\u00a0and <code>foreach<\/code>\u00a0loops that execute the loop bodies on separate threads. It\u2019s simple to use, though requires slightly different syntax:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7379\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/b84257e4a99799b0ef6d7d93e02a3a7e\/p\/uploads\/2020\/10\/3d3a671c.png\" alt=\"\" width=\"464\" height=\"203\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Obviously, the catch here is that you need to make sure <code>DoSomething()<\/code>\u00a0is thread safe, and doesn\u2019t interfere with any shared variables. However, that isn\u2019t always as easy as just replacing the loop with a parallel loop, and in many cases you must <code>lock<\/code>\u00a0shared objects to make changes.<\/p>\n<p>To alleviate some of the issues with deadlocks, <code>Parallel.For<\/code> and <code>Parallel.ForEach<\/code>\u00a0provide extra features for dealing with state. Basically, not every iteration is going to run on a separate thread\u2014if you have 1000 elements, it\u2019s not going to create 1000 threads; it\u2019s going to make as many threads as your CPU can handle, and run multiple iterations per thread. This means that if you\u2019re computing a total, you don\u2019t need to lock for every iteration. You can simply pass around a subtotal variable, and at the very end, lock the object and make changes once. This drastically reduces the overhead on very large lists.<\/p>\n<p>Let\u2019s take a look at an example. The following code takes a big list of objects, and needs to serialize each one separately to JSON, ending up with a <code>List&lt;string&gt;<\/code>\u00a0of all the objects. JSON serialization is a very slow process, so splitting each element over multiple threads is a big speedup.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7378\" src=\"https:\/\/www.cloudsavvyit.com\/thumbcache\/0\/0\/d888ffc813d091add58c8e0e975ac01e\/p\/uploads\/2020\/10\/b58af127.png\" alt=\"\" width=\"608\" height=\"444\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>There\u2019s a bunch of arguments, and a lot to unpack here:<\/p>\n<ul>\n<li>The first argument takes an IEnumerable, which defines the data it\u2019s looping over. This is a ForEach loop, but the same concept works for basic For loops.<\/li>\n<li>The first action initializes the local subtotal variable. This variable will be shared over each iteration of the loop, but only inside the same thread. Other threads will have their own subtotals. Here, we\u2019re initializing it to an empty list. If you were computing a numeric total, you could <code>return 0<\/code>\u00a0here.<\/li>\n<li>The second action is the main loop body. The first argument is the current element (or the index in a For loop), the second is a ParallelLoopState object that you can use to call <code>.Break()<\/code>, and the last is the subtotal variable.\n<ul>\n<li>In this loop, you can operate on the element, and modify the subtotal. The value you return will replace the subtotal for the next loop. In this case, we serialize the element to a string, then add the string to the subtotal, which is a List.<\/li>\n<\/ul>\n<\/li>\n<li>Finally, the last action takes the subtotal \u2018result\u2019 after all the executions have finished, allowing you to lock and modify a resource based on the final total. This action runs once, at the very end, but it still runs on a separate thread, so you will need to lock or use Interlocked methods to modify resources. Here, we call <code>AddRange()<\/code>\u00a0to append the subtotal list to the final list.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Unity_Multithreading\"><\/span>Unity Multithreading<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>One final note\u2014if you\u2019re using the Unity <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/game\/\" data-internallinksmanager029f6b8e52c=\"7\" title=\"Game\" target=\"_blank\" rel=\"noopener\">game<\/a> engine, you\u2019ll want to be careful with multithreading. You can\u2019t call any Unity APIs, or else the game will crash. It\u2019s possible to use it sparingly by doing API operations on the main thread and switching back and forth whenever you need to parallelize something.<\/p>\n<p>Mostly, this applies to operations that interact with the scene or physics engine. Vector3 math is unaffected, and you\u2019re free to use it from a separate thread without issues. You\u2019re also free to modify fields and properties of your own objects, provided that they don\u2019t call any Unity operations under the hood.\n<\/p><\/div>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener noreferrer\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/7374\/how-to-multithread-safely-and-efficiently-in-net\/\" target=\"_blank\" rel=\"noopener noreferrer\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How To Multithread Safely and Efficiently in .NET \u2013 CloudSavvy IT&#8221; Multithreading can be used to drastically speed up the performance of your application, but no speedup is free\u2014managing parallel threads requires careful programming, and without the proper precautions, you can run into race conditions, deadlocks, and even crashes. What Makes Multithreading Hard? Unless you&#8230;<\/p>\n","protected":false},"author":1,"featured_media":90744,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2020\/08\/b476fc9b.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-90743","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/90743","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=90743"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/90743\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/90744"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=90743"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=90743"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=90743"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}